2015-03-21 3 views
2

Я выделил следующий код на детской площадке. В детской площадке, я получаю отмеченные ошибки компиляции времени:Неявно развернутое умножение и деление

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? Есть что-то, чего я не хватал в течение многих лет относительно * = и/=?

Я все еще учусь на это, так что я, вероятно, не хватает какой-то основное свойство.

ответ

4

Вы можете сделать работу * = оператор, явно разворачивает необязательный первый так:

func toOunces() { 
    weight! *= 0.035274 
} 

Вы можете понять, почему это смотрит на то, как * = определяется.

func *=(inout lhs: Double, rhs: Double) 

Для неявно развернутая по желанию не может быть передан в качестве параметра INOUT, потому что он является оболочкой вокруг двойного (или ноль.)

Номера аргументы INOUT могут быть развернуты автоматически, так как функция только нуждается значение, которое можно извлечь из опционального автоматически, а не ссылку на фактическое значение. Вот почему оператор * работает для Double!, который определяется как таковой.

func *(lhs: Double, rhs: Double) -> Double 

Добавление! после того, как вес вашего кода изменит его, передайте ссылку на опцию, чтобы передать ссылку на 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

Ну, я думаю, что у меня есть ответ, но вы не собираетесь это нравится.

*= определяется как такой

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. В обоих случаях сообщение об ошибке выбирает первую версию метода оператора для сообщения об ошибке.

Смежные вопросы