计算属性:get 和 set 之间的不同类型
Posted
技术标签:
【中文标题】计算属性:get 和 set 之间的不同类型【英文标题】:Computed property: different types between get and set 【发布时间】:2017-04-27 07:31:54 【问题描述】:我想将浮点数范围映射到字符串。具体来说,我想转换风的度数方向,例如,在具有基本方向的相应字符串中:220 -> SW
可以使用自定义get
声明创建声明为Float
类型的计算属性,以返回相应的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
如果不是,我有什么可能产生相同的行为?
【问题讨论】:
我也很想看到答案,但老实说,我希望答案是响亮的“不”:-) 答案是不,你实际上需要ValueTransformer
【参考方案1】:
据我所知,这是不可能的。 计算属性仍然是只能是单一类型的属性。
也就是说,也许你最好有自己的类型:
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 个不同的属性。
【讨论】:
这是处理这种情况的更好方法。 顺便说一句:遵守CustomStringConvertible
并将stringValue
重命名为description
将获得更多好处。【参考方案2】:
我想也许你可以像这样使用枚举
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")
【讨论】:
请注意,与11.25..<385
的模式匹配将为[11.25, 385.0)
范围内的任何值产生N
(北),即180
,这是南:)
是的,我没注意到【参考方案3】:
不要这样做!不要这样做!!永远不要这样做。我无法用言语来解释这是多么糟糕的想法。
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
【讨论】:
【参考方案4】:(您应该看看与CustomStringConvertible
的一致性,但对于技术讨论,以下...)
您可以,但是实现一个enum
包装器,其中每个案例包装不同类型的关联值(很像Optional<Int>
包装.none
或.some(Int)
)。
enum WindDirection
case asDegree(Float)
case asString(String)
这样,您可以让您的实例变量windDirection
成为两种不同包装类型的包装器,这将允许您在setter 中期望一种包装类型并在getter 中返回另一种包装类型。例如:
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
示例用法(但是,您需要在调用实例属性时处理包装的关联值的展开)
// attempt initialization
if let foo = Foo(.asDegree(11.0))
// getter
if case .asString(let windDirection) = foo.windDirection
print(windDirection) // N
// setter
foo.windDirection = .asDegree(15.75)
// getter
if case .asString(let windDirection) = foo.windDirection
print(windDirection) // NE
【讨论】:
以上是关于计算属性:get 和 set 之间的不同类型的主要内容,如果未能解决你的问题,请参考以下文章