A Java-based application that demonstrates measurement equality comparison using object-oriented principles.
Checks equality of two numerical values in feet, handling null, type mismatch, and floating-point precision.
- Input two numerical values in feet.
- Validate inputs are numeric.
- Compare for equality → return
trueorfalse.
- Override
equals()usingDouble.compare()instead of== private finalfield for immutability- Null & type safety to prevent exceptions
Extends UC1 to support equality checks for both Feet and Inches independently using separate classes. Reduces main method dependency via static helper methods.
- Static method validates two feet values → compares equality.
- Static method validates two inches values → compares equality.
- Returns
true/falsefor each comparison.
- Separate
Inchesclass mirroringFeet(same equality logic) - Static methods for Feet and Inches equality checks
- Violates DRY principle (addressed in UC3)
Refactors Feet and Inches into a single QuantityLength class using a LengthUnit enum. Eliminates code duplication and supports cross-unit equality (e.g., 1 foot == 12 inches).
- Input value + unit type → validate.
- Convert both values to base unit (feet).
- Compare converted values → return
true/false.
LengthUnitenum with conversion factors- Single class handles all unit types (DRY)
- Cross-unit equality via base unit normalization
Extends UC3 by adding YARDS (1 yd = 3 ft) and CENTIMETERS (1 cm = 0.393701 in) to the LengthUnit enum. No changes to QuantityLength class required.
- Input value + unit (feet/inches/yards/cm) → validate.
- Convert both to base unit (feet).
- Compare → return
true/false.
| Unit | Factor (to feet) |
|---|---|
| YARDS | 3.0 |
| CENTIMETERS | ~0.0328 |
Extends UC4 by exposing an explicit convert(value, sourceUnit, targetUnit) method. Normalizes to base unit (feet) then converts to target unit. Introduces method overloading and JavaDoc documentation.
- Validate value (finite), sourceUnit and targetUnit (non-null).
- Convert value → base unit using
sourceUnit.getConversionFactor(). - Convert base unit → target using
targetUnit.getConversionFactor(). - Return converted numeric value.
- Method overloading:
demonstrateLengthConversion(double, LengthUnit, LengthUnit)and(QuantityLength, LengthUnit) - Private helper methods for encapsulation
toString()override for readability- Formula:
result = value × (source.factor / target.factor)
Extends UC5 by adding two QuantityLength objects (potentially different units). Result is expressed in the unit of the first operand. Both operands are normalized to base unit before summing.
- Validate both operands (non-null, finite, valid units).
- Convert both to base unit (feet).
- Sum converted values.
- Convert sum → first operand's unit.
- Return new
QuantityLength(immutability preserved).
- Immutability: addition returns new instance
- Commutativity:
add(A, B)=add(B, A) - Method overloading for flexible API
Extends UC6 by allowing the caller to specify any supported unit as the result unit, regardless of the operands' units. Uses a private utility method to avoid code duplication across overloaded add() methods.
- Validate operands and target unit (non-null, finite).
- Convert both to base unit → sum.
- Convert sum → explicitly specified
targetUnit. - Return new
QuantityLengthin target unit.
- Method overloading:
add(l1, l2)implicit vsadd(l1, l2, targetUnit)explicit - Private utility method eliminates DRY violation between overloads
- Commutativity holds for any target unit
Extracts LengthUnit from inside QuantityLength into a standalone top-level class. Assigns conversion responsibility to the enum itself. QuantityLength is simplified to delegate all conversions to unit methods. All UC1–UC7 functionality preserved.
LengthUnitenum handlesconvertToBaseUnit()andconvertFromBaseUnit().QuantityLengthdelegates all conversions to unit methods.- Public API remains unchanged → backward compatible.
- Single Responsibility:
LengthUnitconverts,QuantityLengthcompares/adds - Eliminates circular dependency for multi-category scaling
- Pattern template for future
WeightUnit,VolumeUnit, etc.
Introduces a new WeightUnit enum and QuantityWeight class mirroring the UC8 length pattern. Supports equality, conversion, and addition for KILOGRAM, GRAM, and POUND. Weight and length are incompatible categories.
| Unit | Factor |
|---|---|
| KILOGRAM | 1.0 |
| GRAM | 0.001 |
| POUND | 0.453592 |
WeightUnitstandalone enum withconvertToBaseUnit()/convertFromBaseUnit()- Category type safety:
Quantity(1.0, KG).equals(Quantity(1.0, FOOT))→false - Overloaded
add(): implicit (first operand unit) and explicit (target unit) hashCode()overridden consistently withequals()
Refactors QuantityLength and QuantityWeight into a single generic Quantity<U extends IMeasurable> class. Eliminates code duplication across categories using a common interface. All UC1–UC9 functionality preserved.
| Component | Responsibility |
|---|---|
IMeasurable |
Defines unit conversion contract |
LengthUnit / WeightUnit |
Implement IMeasurable with conversion factors |
Quantity<U> |
Handles equality, conversion, addition for any unit |
QuantityMeasurementApp |
Generic demonstration only |
- Bounded type parameter
<U extends IMeasurable>for compile-time type safety - Cross-category prevention via
unit.getClass()comparison equals(),convertTo(),add()implemented once — reused for all categories- Adding new categories requires ONLY a new enum implementing
IMeasurable
Adds a third measurement category — volume — by creating a VolumeUnit enum implementing IMeasurable. No changes to Quantity<U>, QuantityMeasurementApp, or existing tests required. Proves the UC10 architecture scales linearly.
| Unit | Factor |
|---|---|
| LITRE | 1.0 |
| MILLILITRE | 0.001 |
| GALLON | 3.78541 |
- Only a new enum needed to add a full measurement category
- Cross-category safety:
1.0 LITRE ≠ 1.0 KILOGRAMand1.0 LITRE ≠ 1.0 FOOT - All generic
Quantity<U>operations work automatically
Extends Quantity<U> with subtraction (returns Quantity<U>) and division (returns dimensionless double). Both operations support cross-unit arithmetic within the same category and maintain immutability.
| Method | Returns | Notes |
|---|---|---|
subtract(other) |
Quantity<U> |
Result in first operand's unit |
subtract(other, targetUnit) |
Quantity<U> |
Result in explicit unit |
divide(other) |
double |
Dimensionless ratio |
- Subtraction is non-commutative:
A - B ≠ B - A - Division is non-commutative:
A ÷ B ≠ B ÷ A - Division by zero throws
ArithmeticException - Cross-category operations throw
IllegalArgumentException
Refactors UC12's add(), subtract(), and divide() to eliminate duplicated validation and conversion logic by introducing a centralized private helper method and an ArithmeticOperation enum. Public API is unchanged; all UC12 behavior preserved.
| Component | Role |
|---|---|
ArithmeticOperation enum |
Dispatches ADD, SUBTRACT, DIVIDE via compute(a, b) |
validateArithmeticOperands() |
Centralized null, category, finiteness checks |
performBaseArithmetic() |
Converts to base unit → executes operation → returns result |
- Abstract method: Each constant overrides
compute()— clean for complex logic - Lambda (
DoubleBinaryOperator): Concise, modern functional style
- All validation defined once → consistent errors across all operations