计算属性:get和set之间的不同类型

时间:2016-12-12 12:17:45

标签: ios swift swift3 computed-properties

我想将float的范围映射到字符串。在细节中,我想转换风的度数方向,例如,在具有基本方向的相应字符串中:220 - > SW

可以使用自定义Float声明创建声明类型为get的计算属性,以便返回相应的String?通过这种方式,我会将其写为Float,但我会将其读作String

类似的东西:

var windDirection: Float? {
    get {
        switch self.windDirection {
        case 348.75..<11.25:
            return "N"
            break
        ...
        default:
            break
        }
    }
    set (newValue) {
        self.windDirection = newValue
    }
}

如果没有,我有什么可能产生相同的行为?

4 个答案:

答案 0 :(得分:2)

据我所知,这是不可能的。 计算属性仍然是一个只能是单一类型的属性。

那就是说,也许你最好拥有自己的类型:

struct WindDirection {
    var degrees: Float
    var stringValue: String {
        get {
            // compute the correct string here
            return "\(degrees)"
        }
        set {
            // compute the correct float value here
            degrees = Float(newValue) ?? 0
        }

    }
}

var windDirection: WindDirection

如果您不想使用自己的类型,那么您将不得不坚持使用2种不同的属性。

答案 1 :(得分:1)

我想也许你可以这样使用枚举

enum Wind {
    case degree(Float)
    case direction(String)
}

extension Wind {

    init?(degree: Float) {
        switch degree {
        case 11.25..<385:
            self = .direction("N")
        default:
            return nil
        }
    }

}

let wind = Wind(degree: 100) // Result is direction("N")

答案 2 :(得分:0)

不要这样做!不要这样做!!从来没有这样做过。我不会用这些词来解释这个想法有多糟糕。

private var _windDirection: Float?

var windDirection: Any? {
    get {
        guard let windDirection = _windDirection else {
            return nil
        }

        switch windDirection {
        case 348.75..<11.25:
            return "N"
        ...
        default:
            return nil
        }
    }
    set (newValue) {
        guard let windDirection = newValue as? Float else {
            _windDirection = nil
            return
        }

        _windDirection = windDirection
    }
}

答案 3 :(得分:0)

(您应该查看与CustomStringConvertible的一致性,但是对于技术讨论,请遵循以下内容......)

可以,但实现enum包装器,其中每个案例包含不同类型的关联值(非常类似于Optional<Int>换行.none或{{1} })。

.some(Int)

有了这个,你可以让你的实例变量enum WindDirection { case asDegree(Float) case asString(String) } 成为两个不同包装类型的包装器,这将允许你在setter中期望一个包装类型,并在getter中返回另一个包装器类型。 E.g:

windDirection

示例用法(但是,您需要在调用实例属性时处理包装的关联值的展开)

class Foo {
    private var _windDirection: WindDirection
    var windDirection: WindDirection {
        get {
            switch _windDirection {
            case .asDegree(let angle):
                switch(angle) {
                case 348.75..<360.0, 0..<11.25: return .asString("N")
                case 11.25..<33.75: return .asString("NE")
                /* ... */
                case _ : return .asString("Not expected")
                }
            case _ : return .asString("Not expected")
            }
        }
        set (newValue) {
            if case .asDegree(_) = newValue {
                _windDirection = newValue
            }
        }
    }

    init?(_ windDirection: WindDirection) {
        guard case .asDegree(_) = windDirection else { return nil }
        _windDirection = windDirection
    }
}