我在游乐场中隔离了以下代码。在操场上,我得到了注意到的编译时错误:
class MyClass {
var weight: Double!
func toOunces() {
weight *= 0.035274 // 'Double!' is not identical to 'UInt8'
weight = weight * 0.035274 // works
}
func toGrams() {
weight /= 0.035274 // 'Double!' is not identical to 'Float'
weight = weight / 0.035274 // works
}
}
我正在使用NSCoder在线跟踪示例,其中使用了decodeDoubleForKey() as Double?
,因此隐式展开了可选的var weight: Double!
。
我正在辩论这是多么正确,我在我的代码中修复了它。
我的问题是,为什么这些编译时错误?为什么乘法与UInt8相比,除法与Float相比?多年来我有没有关于* =和/ =?
的事情我还在学习这个,所以我可能错过了一些基本属性。
答案 0 :(得分:4)
你可以通过显式展开可选的第一个来使* =运算符工作:
func toOunces() {
weight! *= 0.035274
}
您可以看到为什么要查看* =是如何定义的。
func *=(inout lhs: Double, rhs: Double)
隐式展开的可选项不能作为inout参数传递,因为它是Double(或nil。)的包装器
非inout参数可以自动解包,因为该函数只需要可以从可选中自动提取的值,而不是对实际值的引用。这就是为什么*运算符适用于Double!
的原因。
func *(lhs: Double, rhs: Double) -> Double
添加!代码中的权重更改后,将引用传递给可选引用,将引用传递给Optional中包含的Double。如果* =具有正常的函数语法并且我们删除了一些糖,它可能看起来像这样:
func multiplyAssign (inout lhs: Double, rhs: Double){
lhs = rhs * lhs
}
var weight: ImplicitlyUnwrappedOptional<Double> = 0.0
multiplyAssign(&weight, 10.0) //trying to pass reference to an ImplicitlyUnwrappedOptional<Double> (error)
multiplyAssign(&(weight!), 10.0) //passing a reference to a Double
答案 1 :(得分:1)
我认为我有答案,但你不会喜欢它。
*=
被定义为
func *=(inout lhs: UInt8, rhs: UInt8)
func *=(inout lhs: Int8, rhs: Int8)
func *=(inout lhs: UInt16, rhs: UInt16)
func *=(inout lhs: Int16, rhs: Int16)
func *=(inout lhs: UInt32, rhs: UInt32)
func *=(inout lhs: Int32, rhs: Int32)
func *=(inout lhs: UInt64, rhs: UInt64)
func *=(inout lhs: Int64, rhs: Int64)
func *=(inout lhs: UInt, rhs: UInt)
func *=(inout lhs: Int, rhs: Int)
func *=(inout lhs: Float, rhs: Float)
func *=(inout lhs: Double, rhs: Double)
/// multiply `lhs` and `rhs` and store the result in `lhs`, trapping in
/// case of arithmetic overflow (except in -Ounchecked builds).
func *=<T : _IntegerArithmeticType>(inout lhs: T, rhs: T)
func *=(inout lhs: Float80, rhs: Float80)
/=
定义为
func /=(inout lhs: Float, rhs: Float)
func /=(inout lhs: Double, rhs: Double)
func /=(inout lhs: Float80, rhs: Float80)
/// divide `lhs` and `rhs` and store the result in `lhs`, trapping in
/// case of arithmetic overflow (except in -Ounchecked builds).
func /=<T : _IntegerArithmeticType>(inout lhs: T, rhs: T)
/
和*
运算符的第一个参数没有inout
说明符,分别为/=
和*=
。我注意到的另一件事是UInt8
是第一个*=
运算符,Float
是第一个/=
运算符。
将所有内容放在一起,Double!
可以强制转换为Double
,但不能强制转换为inout Double
。在这两种情况下,错误消息都是选择第一个版本的operator方法来报告错误。