Sample code demonstrating using Kotlin for type safe unit conversion
val miles = 1.kilometers.to(Distance.Mile) | |
val kilometers = 1.miles.to(Distance.Kilometer) | |
val total = 2.kilometers + 1.miles + 10.meters + 1.centimeter + 1.millimeter | |
Log.d("MainActivity", "Total distance is ${total.meters.amount} meters") | |
val totalTime = 2.hours + 2.minutes + 2.seconds + 2.milliseconds | |
Log.d("MainActivity", "Total time is ${totalTime.amount} ${totalTime.unit}") |
open class Unit(val name: String, val ratio: Double) { | |
fun convertToBaseUnit(amount: Double) = amount * ratio | |
fun convertFromBaseUnit(amount: Double) = amount / ratio | |
} | |
open class Quantity<T: Unit>(val amount: Double, val unit: T) { | |
fun to(unit: T): Quantity<T> { | |
val baseUnit = this.unit.convertToBaseUnit(amount) | |
return Quantity(unit.convertFromBaseUnit(baseUnit), unit) | |
} | |
operator fun plus(quantity: Quantity<T>): Quantity<T> { | |
val converted = quantity.to(this.unit).amount | |
val amount = this.amount + converted | |
return Quantity(amount, this.unit) | |
} | |
operator fun minus(quantity: Quantity<T>): Quantity<T> { | |
val converted = quantity.to(this.unit).amount | |
val amount = this.amount - converted | |
return Quantity(amount, this.unit) | |
} | |
operator fun times(quantity: Quantity<T>): Quantity<T> { | |
val converted = quantity.to(this.unit).amount | |
val amount = this.amount * converted | |
return Quantity(amount, this.unit) | |
} | |
operator fun div(quantity: Quantity<T>): Quantity<T> { | |
val converted = quantity.to(this.unit).amount | |
val amount = this.amount / converted | |
return Quantity(amount, this.unit) | |
} | |
} | |
class Distance(name: String, ratio: Double) : Unit(name, ratio) { | |
companion object Factory { | |
val Mile = Distance("Mile", 1.60934 * 1000.0) | |
val Kilometer = Distance("Kilometer", 1000.0) | |
val Meter = Distance("Meter", 1.0) | |
val Centimeter = Distance("Centimeter", 0.01) | |
val Millimeter = Distance("Millimeter", 0.001) | |
} | |
} | |
val Quantity<Distance>.miles get() = this.to(Distance.Mile) | |
val Quantity<Distance>.kilometers get() = this.to(Distance.Kilometer) | |
val Quantity<Distance>.meters get() = this.to(Distance.Meter) | |
val Quantity<Distance>.centimeters get() = this.to(Distance.Centimeter) | |
val Quantity<Distance>.millimeters get() = this.to(Distance.Millimeter) | |
val Number.meters: Quantity<Distance> get() = Quantity(this.toDouble(), Distance.Meter) | |
val Number.kilometers: Quantity<Distance> get() = Quantity(this.toDouble(), Distance.Kilometer) | |
val Number.miles: Quantity<Distance> get() = Quantity(this.toDouble(), Distance.Mile) | |
val Number.centimeter: Quantity<Distance> get() = Quantity(this.toDouble(), Distance.Centimeter) | |
val Number.millimeter: Quantity<Distance> get() = Quantity(this.toDouble(), Distance.Millimeter) | |
class Time(name: String, ratio: Double) : Unit(name, ratio) { | |
companion object Factory { | |
val Hour = Time("Hour", TimeUnit.HOURS.toMillis(1L).toDouble()) | |
val Minute = Time("Minute", TimeUnit.MINUTES.toMillis(1L).toDouble()) | |
val Second = Time("Second", TimeUnit.SECONDS.toMillis(1L).toDouble()) | |
val Millisecond = Time("Millisecond", 1.0) | |
} | |
} | |
val Quantity<Time>.hours get() = this.to(Time.Hour) | |
val Quantity<Time>.minutes get() = this.to(Time.Minute) | |
val Quantity<Time>.seconds get() = this.to(Time.Second) | |
val Quantity<Time>.milliseconds get() = this.to(Time.Millisecond) | |
val Number.hours: Quantity<Time> get() = Quantity(this.toDouble(), Time.Hour) | |
val Number.minutes: Quantity<Time> get() = Quantity(this.toDouble(), Time.Minute) | |
val Number.seconds: Quantity<Time> get() = Quantity(this.toDouble(), Time.Second) | |
val Number.milliseconds: Quantity<Time> get() = Quantity(this.toDouble(), Time.Millisecond) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
How comes that you multiply Distance by Distance and get Distance in result?