class

Unit::Measurement(T, U)

Inherits Unit::Formatter < Unit::Conversion < Unit::Arithmetic < Reference < Object

Generic measurement class with phantom types for compile-time type safety

This class provides the foundation for all measurement types in the Unit library. It uses Crystal's phantom types to ensure type safety at compile time, preventing operations between incompatible measurement types.

The class is parameterized by:

  • T: The measurement type (e.g., Weight, Length, Volume)
  • U: The unit enum type specific to that measurement

Type Safety

The phantom type system prevents mixing incompatible measurements:

weight = Unit::Weight.new(10, :kilogram)
length = Unit::Length.new(5, :meter)
# weight + length  # Compile error! Cannot add Weight to Length

Precision

All values are stored internally as BigDecimal to maintain precision across conversions and arithmetic operations.

Examples

# Creating measurements
weight = Unit::Weight.new(5.5, :kilogram)
length = Unit::Length.new(100, :centimeter)

# Converting units
pounds = weight.convert_to(:pound)
meters = length.to(:meter)

# Arithmetic operations
total = weight + Unit::Weight.new(10, :pound)
double = weight * 2

Constructors

new(value : Number, unit : U)

Creates a new measurement with the given value and unit.

The value is automatically converted to BigDecimal for precision preservation. This constructor accepts any numeric type supported by Crystal.

Parameters

  • value: The numeric value (Int32, Int64, Float32, Float64, BigDecimal, BigRational)
  • unit: The unit enum value or symbol

Examples

# Using enum values
Unit::Weight.new(10, Unit::Weight::Unit::Kilogram)

# Using symbols (convenient shorthand)
Unit::Weight.new(10, :kilogram)

# Various numeric types
Unit::Weight.new(10_i32, :kilogram)                 # Int32
Unit::Weight.new(10.5_f64, :kilogram)               # Float64
Unit::Weight.new(BigDecimal.new("10.5"), :kilogram) # BigDecimal

Raises

  • ArgumentError if value is NaN
  • ArgumentError if value is infinite
Source

Instance methods

==(other : Measurement(T, U)) : Bool

Compares two measurements for equality.

Two measurements are considered equal if they have the same value and unit. This method only compares measurements of the same type due to phantom typing.

Note: For comparing measurements with different units, use the comparison operators (>, <, etc.) which handle unit conversion automatically.

kg1 = Unit::Weight.new(1, :kilogram)
kg2 = Unit::Weight.new(1, :kilogram)
g1000 = Unit::Weight.new(1000, :gram)

kg1 == kg2   # => true (same value and unit)
kg1 == g1000 # => false (different units, use comparison operators instead)
Source
hash(hasher)

Generates a hash value for use in Hash collections.

The hash is based on both the value and unit to maintain consistency with the equality operator.

weights = {} of Unit::Weight => String
weight = Unit::Weight.new(5.5, :kilogram)
weights[weight] = "medium"
Source
inspect(io : IO) : Nil

Returns a detailed string representation for debugging.

Shows the measurement's type parameters and internal structure, useful for development and debugging purposes.

weight = Unit::Weight.new(5.5, :kilogram)
weight.inspect # => "Measurement(Unit::Weight, Unit::Weight::Unit)(5.5, Kilogram)"
Source
to_json(json : JSON::Builder) : Nil

Serializes the measurement to JSON format.

The value is stored as a string to preserve BigDecimal precision, and the unit is stored as its string representation.

weight = Unit::Weight.new(5.5, :kilogram)
weight.to_json # => {"value":"5.5","unit":"kilogram"}
Source
to_yaml(yaml : YAML::Nodes::Builder) : Nil

Serializes the measurement to YAML format.

The value is stored as a string to preserve BigDecimal precision, and the unit is stored as its string representation.

weight = Unit::Weight.new(5.5, :kilogram)
weight.to_yaml # => "---\nvalue: '5.5'\nunit: kilogram\n"
Source
unit

The unit of measurement as an enum value.

weight = Unit::Weight.new(5.5, :kilogram)
weight.unit # => Unit::Weight::Unit::Kilogram
Source
value

The numeric value of the measurement, stored as BigDecimal for precision.

weight = Unit::Weight.new(5.5, :kilogram)
weight.value # => BigDecimal("5.5")
Source