I am dealing with different units, i.e. distance
, altitude
, speed
, volume
, etc.
My goal is to have an elegant, unique way to format them in the app, like for example calling myValue.formatted
:
let mySpeed: Speed = 180
println(mySpeed.formatted) // 5.0 km/h
let myAltitude: Altitude = 4000
println(myAltitude.formatted) // 4000 m
I thought this was a good case for using type aliases.
typealias Distance = Float
typealias Altitude = Float
typealias Speed = Float
For the formatted
property, I tried with an extension
of the type Float
:
extension Float {
var formatted: String {
get {
switch self {
case is Altitude:
return "\(self) m"
case is Speed:
return "\(self * 3.6) km/h"
default:
return "\(self)"
}
}
}
}
But the compiler says that my case
blocks are always true
.
Then i tried to extend the single type:
extension Speed {
var formatted: String {
return "\(self * 3.6) km/h"
}
}
extension Altitude {
var formatted: String {
return "\(self) m"
}
}
the compiler now clearly states Invalid redeclaration of 'formatted'
OK, it's clear now how type aliases work. But how would I get my .formatted
property for different types of Floats in swift?
typealias
just change or rename the type. It does not create another user type for you. You are actually extending Float
for Speed
, Altitude
again.
You can pass 180
to your custom struct by conforming Literals
types.
let mySpeed: Speed = 180
FloatLiteralConvertible
and IntegerLiteralConvertible
will give you same functionality you want and you can directly assign values to your custom struct types
as you assign to Float
struct Speed: FloatLiteralConvertible,IntegerLiteralConvertible {
var distance:Float
init(floatLiteral value: Float) {
distance = value
}
init(integerLiteral value: Int){
distance = Float(value)
}
var formatted: String {
return "\(distance * 3.6) km/h"
}
}
let mySpeed: Speed = 180.0
println(mySpeed.formatted) // 5.0 km/h
Distance
, Altitude
, and Speed
is always the same type - Float
and share the same formatted
property. This is how compiler sees your code:
extension Float {
var formatted: String {
get {
switch self {
case is Float:
return "\(self) m"
case is Float:
return "\(self * 3.6) km/h"
default:
return "\(self)"
}
}
}
}
I guess you need to create small wrappers for your functionality:
struct Distance {
var value: Float
var formatted: String {
return "\(value) m"
}
init(_ value: Float) {
self.value = value
}
}
let myDistance = Distance(123)
myDistance.formatted
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With