隐含地解开了乘法和除法

时间:2015-03-21 01:33:13

标签: swift

我在游乐场中隔离了以下代码。在操场上,我得到了注意到的编译时错误:

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相比?多年来我有没有关于* =和/ =?

的事情

我还在学习这个,所以我可能错过了一些基本属性。

2 个答案:

答案 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方法来报告错误。