* For example, to get a unit representing the degree Celsius, the following code can be used: * * {@code Unit.fromConversionFunctions(SI.KELVIN, tempK -> tempK - 273.15, tempC -> tempC + 273.15);} *
* * @param base * unit's base * @param converterFrom * function that accepts a value expressed in the unit's base and returns that value expressed in this * unit. * @param converterTo * function that accepts a value expressed in the unit and returns that value expressed in the unit's * base. * @return a unit that uses the provided functions to convert. * @since 2019-05-22 * @throws NullPointerException * if any argument is null */ public static final Unit fromConversionFunctions(final ObjectProduct* For example, to get a unit representing the degree Celsius, the following code can be used: * * {@code Unit.fromConversionFunctions(SI.KELVIN, tempK -> tempK - 273.15, tempC -> tempC + 273.15);} *
* * @param base * unit's base * @param converterFrom * function that accepts a value expressed in the unit's base and returns that value expressed in this * unit. * @param converterTo * function that accepts a value expressed in the unit and returns that value expressed in the unit's * base. * @param ns * names and symbol of unit * @return a unit that uses the provided functions to convert. * @since 2019-05-22 * @throws NullPointerException * if any argument is null */ public static final Unit fromConversionFunctions(final ObjectProduct* This must be the inverse of {@code convertToBase}, so {@code convertFromBase(convertToBase(value))} must be equal * to {@code value} for any value, ignoring precision loss by roundoff error. *
** If this unit is a base unit, this method should return {@code value}. *
* * @implSpec This method is used by {@link #convertTo}, and its behaviour affects the behaviour of * {@code convertTo}. * * @param value * value expressed in base unit * @return value expressed in this unit * @since 2018-12-22 * @since v0.1.0 */ protected abstract double convertFromBase(double value); /** * Converts a value expressed in this unit to a value expressed in {@code other}. * * @implSpec If unit conversion is possible, this implementation returns * {@code other.convertFromBase(this.convertToBase(value))}. Therefore, overriding either of those methods * will change the output of this method. * * @param other * unit to convert to * @param value * value to convert * @return converted value * @since 2019-05-22 * @throws IllegalArgumentException * if {@code other} is incompatible for conversion with this unit (as tested by * {@link Unit#canConvertTo}). * @throws NullPointerException * if other is null */ public final double convertTo(final Unit other, final double value) { Objects.requireNonNull(other, "other must not be null."); if (this.canConvertTo(other)) return other.convertFromBase(this.convertToBase(value)); else throw new IllegalArgumentException(String.format("Cannot convert from %s to %s.", this, other)); } /** * Converts from a value expressed in this unit to a value expressed in this unit's base unit. ** This must be the inverse of {@code convertFromBase}, so {@code convertToBase(convertFromBase(value))} must be * equal to {@code value} for any value, ignoring precision loss by roundoff error. *
** If this unit is a base unit, this method should return {@code value}. *
* * @implSpec This method is used by {@link #convertTo}, and its behaviour affects the behaviour of * {@code convertTo}. * * @param value * value expressed in this unit * @return value expressed in base unit * @since 2018-12-22 * @since v0.1.0 */ protected abstract double convertToBase(double value); /** * @return combination of units that this unit is based on * @since 2018-12-22 * @since v0.1.0 */ public final ObjectProduct