/**
* Copyright (C) 2019 Adrien Hopkins
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see
* With the addition of {@link Unit#fromConversionFunctions}, there is no longer any reason to use {@code AbstractUnit} * for any purpose other than making subclasses. Units should never be declared as {@code AbstractUnit}, they should be * declared as {@code Unit}. Now that {@code Unit.fromConversionFunctions} exists, it is preferred to creating anonymous * inner types of {@code AbstractUnit}. *
* * @author Adrien Hopkins * @since 2018-12-22 * @since v0.1.0 */ public abstract class AbstractUnit implements Unit { /** * The dimension, or what the unit measures. * * @since 2018-12-22 * @since v0.1.0 */ private final UnitDimension dimension; /** * The unit's base unit. Values converted by {@code convertFromBase} and {@code convertToBase} are expressed in this * unit. * * @since 2018-12-22 * @since v0.1.0 */ private final BaseUnit base; /** * The system that this unit is a part of. * * @since 2018-12-23 * @since v0.1.0 */ private final UnitSystem system; /** * Creates the {@code AbstractUnit}. * * @param base * unit's base * @throws NullPointerException * if name, symbol or base is null * @since 2018-12-22 * @since v0.1.0 */ public AbstractUnit(final BaseUnit base) { this.base = Objects.requireNonNull(base, "base must not be null."); this.dimension = this.base.getDimension(); this.system = this.base.getSystem(); } /** * Creates the {@code AbstractUnit} using a unique dimension. This constructor is for making base units and should * only be used by {@code BaseUnit}. * * @param dimension * dimension measured by unit * @param system * system that unit is a part of * @throws AssertionError * if this constructor is not run by {@code BaseUnit} or a subclass * @throws NullPointerException * if name, symbol or dimension is null * @since 2018-12-23 * @since v0.1.0 */ AbstractUnit(final UnitDimension dimension, final UnitSystem system) { // try to set this as a base unit if (this instanceof BaseUnit) { this.base = (BaseUnit) this; } else throw new AssertionError(); this.dimension = Objects.requireNonNull(dimension, "dimension must not be null."); this.system = Objects.requireNonNull(system, "system must not be null."); } @Override public final BaseUnit getBase() { return this.base; } @Override public final UnitDimension getDimension() { return this.dimension; } @Override public final UnitSystem getSystem() { return this.system; } @Override public String toString() { return String.format("%s-derived unit of dimension %s", this.getSystem(), this.getDimension()); } }