001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package edu.wpi.first.units; 006 007import java.util.Objects; 008 009/** 010 * A measure holds the magnitude and unit of some dimension, such as distance, time, or speed. An 011 * immutable measure is <i>immutable</i> and <i>type safe</i>, making it easy to use in concurrent 012 * situations and gives compile-time safety. Two measures with the same <i>unit</i> and 013 * <i>magnitude</i> are effectively equivalent objects. 014 * 015 * @param <U> the unit type of the measure 016 */ 017public class ImmutableMeasure<U extends Unit<U>> implements Measure<U> { 018 private final double m_magnitude; 019 private final double m_baseUnitMagnitude; 020 private final U m_unit; 021 022 /** 023 * Creates a new immutable measure instance. This shouldn't be used directly; prefer one of the 024 * factory methods instead. 025 * 026 * @param magnitude the magnitude of this measure 027 * @param unit the unit of this measure. 028 */ 029 @SuppressWarnings("unchecked") 030 ImmutableMeasure(double magnitude, double baseUnitMagnitude, Unit<U> unit) { 031 Objects.requireNonNull(unit, "Unit cannot be null"); 032 m_magnitude = magnitude; 033 m_baseUnitMagnitude = baseUnitMagnitude; 034 m_unit = (U) unit; 035 } 036 037 /** 038 * Creates a new measure in the given unit with a magnitude equal to the given one in base units. 039 * 040 * @param <U> the type of the units of measure 041 * @param baseUnitMagnitude the magnitude of the measure, in terms of the base unit of measure 042 * @param unit the unit of measure 043 * @return a new measure 044 */ 045 public static <U extends Unit<U>> ImmutableMeasure<U> ofBaseUnits( 046 double baseUnitMagnitude, Unit<U> unit) { 047 return new ImmutableMeasure<>(unit.fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, unit); 048 } 049 050 /** 051 * Creates a new measure in the given unit with a magnitude in terms of that unit. 052 * 053 * @param <U> the type of the units of measure 054 * @param relativeMagnitude the magnitude of the measure 055 * @param unit the unit of measure 056 * @return a new measure 057 */ 058 public static <U extends Unit<U>> ImmutableMeasure<U> ofRelativeUnits( 059 double relativeMagnitude, Unit<U> unit) { 060 return new ImmutableMeasure<>(relativeMagnitude, unit.toBaseUnits(relativeMagnitude), unit); 061 } 062 063 /** Gets the unitless magnitude of this measure. */ 064 @Override 065 public double magnitude() { 066 return m_magnitude; 067 } 068 069 @Override 070 public double baseUnitMagnitude() { 071 return m_baseUnitMagnitude; 072 } 073 074 /** Gets the units of this measure. */ 075 @Override 076 public U unit() { 077 return m_unit; 078 } 079 080 /** 081 * Checks for <i>object equality</i>. To check if two measures are <i>equivalent</i>, use {@link 082 * #isEquivalent(Measure) isEquivalent}. 083 */ 084 @Override 085 public boolean equals(Object o) { 086 if (this == o) { 087 return true; 088 } 089 if (!(o instanceof Measure)) { 090 return false; 091 } 092 Measure<?> that = (Measure<?>) o; 093 return Objects.equals(m_unit, that.unit()) && m_baseUnitMagnitude == that.baseUnitMagnitude(); 094 } 095 096 @Override 097 public int hashCode() { 098 return Objects.hash(m_magnitude, m_unit); 099 } 100 101 @Override 102 public Measure<U> copy() { 103 return this; // already immutable, no need to allocate a new object 104 } 105 106 @Override 107 public String toString() { 108 return toShortString(); 109 } 110}