在Swift中扩展类型别名

8

我正在处理不同的单位,例如距离高度速度体积等。

我的目标是在应用程序中以优雅且独特的方式格式化它们,例如调用myValue.formatted

let mySpeed: Speed = 180
println(mySpeed.formatted) // 5.0 km/h

let myAltitude: Altitude = 4000
println(myAltitude.formatted) // 4000 m

我认为这是使用类型别名的一个好例子。

typealias Distance = Float
typealias Altitude = Float
typealias Speed = Float

对于formatted属性,我尝试使用类型为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)"
            }
        }
    }
}

但编译器说我的 case 块总是为 true
然后我尝试扩展单个类型:
extension Speed {
  var formatted: String {
    return "\(self * 3.6) km/h"
  }
}
extension Altitude {
  var formatted: String {
    return "\(self) m"
  }
}

编译器现在明确声明“formatted”无效的重新声明。
好的,现在我们清楚了类型别名的工作原理。但是,在Swift中,我如何为不同类型的浮点数获取我的“ .formatted ”属性呢?
2个回答

7

typealias 只是更改或重命名类型,它不会为您创建另一个用户类型。实际上,您正在为 SpeedAltitude 扩展 Float

通过符合 Literals 类型,您可以将 180 传递给自定义结构体。

let mySpeed: Speed = 180
< p > FloatLiteralConvertibleIntegerLiteralConvertible 提供了您想要的相同功能,并且您可以像给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

这确实非常有趣。有点令人失望的是,我无法将floatVar强制转换为Speed,即使用as关键字。类型别名以这种方式很优雅。 - gpbl
@crumblenaut,你是对的。速度现在不是Float了,它是用户自定义的自定义类型。你可以使用一个函数和一种格式来format Float。如果你真的想这样做,在扩展中使用formatSpeedformatDistance - codester

1

距离海拔高度速度始终是相同类型 - 浮点数,并且共享相同的格式化属性。这就是编译器看到您的代码的方式:

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)"
            }
        }
    }
}

我猜您需要为您的功能创建小型包装器:

struct Distance {
    var value: Float
    var formatted: String {
        return "\(value) m"
    }

    init(_ value: Float) {
        self.value = value
    }
}

let myDistance = Distance(123)
myDistance.formatted

谢谢您的见解。不幸的是,用这种方式我无法编写:let mySpeed: Speed = 30。我想我会选择另一种“格式化”解决方案。 - gpbl
你可以使用这种方法进行 let mySpeed = Speed(30.0) - Kirsteins
@crumblenaut 看看这篇文章,了解如何实现字面量赋值。 - Antonio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接