2016-01-14 2 views
2

Рассмотрим следующий код:Почему этот тип проблемный код Swift не генерирует ошибку?

func f(dict: [String: AnyObject]) { 
    let x = dict["mykey"]?.integerValue 
    // Do something with x 
} 

Там нет никаких признаков того, какой тип dict["mike"] может быть, но я могу вызвать integerValue на него. Как этот код не вызывает ошибку или, по крайней мере, предупреждение?

+0

Разъяснения в моей книге онлайн: http://www.apeth.com/swiftBook/ch04.html#SECsuppressing – matt

+0

@ Matt Спасибо за эту ссылку! – dfri

+0

@matt: поэтому мы пытаемся вызвать свойство integerValue в экземпляре 'AnyObject', но это может и не существовать, например. пользовательский тип класса, используемый как значение для некоторого ключа в словаре? – dfri

ответ

0

Возврат от .integerValue является необязательным Int: let x: Int?. Свойство integerValue инициализирует целое число, используя значение для ключа "myKey"; однако, если он не сработает, если он вернет nil.

Если значениеAnyObjectдля определенного ключа в словаре не содержит успешный метода для инициализации целого заданного значения (то есть, по integerValue вычисленной собственности), то последний шагу после опциональных цепочек на x в ваш вопрос выше будет возвращать ноль, например:

class MyClass { 
    var myInt : Int 
    init() { 
     myInt = 1 
    } 
} 

var myDict : [String:AnyObject] = ["myKey":MyClass()] 
let a = myDict["myKey"]    // MyClass, OK 
let x = myDict["myKey"]!.integerValue // nil 

Следовательно, обратите внимание, что это не фактический поиск по ключевому "myKey", который возвращает ноль выше, но попытка вызова собственности .integerValue на экземпляре AnyObject объекта MyClass(), из которого он, естественно, не существует (для компилятора), знает способ построения Int.

2

Это не вызывает ошибки или предупреждения, потому что AnyObject позволяет называть любой метод NSObject эквивалентом id в Objective-C. Поэтому в этом случае компилятор не знает, что он будет там, и если объект не поддерживает integerValue, тогда вы получите 0 в конце его на основании тестирования на игровой площадке.

+0

Да, это будет 0 по внешнему виду на игровой площадке, пропустил дополнительную цепочку. – darren102

+0

Я вижу. Если используется 'AnyObject', тогда все ставки безопасности типа отключены. – Ana

+0

Да, вы можете выполнить кастинг с помощью 'guard/if let as?', Чтобы проверить тип или 'is', но вы можете вызвать практически любой метод в' AnyObject' – darren102

0

? Необязательно-развертывание - это красная сельдь. Было бы лучше, чтобы написать пример, как это:

func f(dict: [String: AnyObject]) { 
    let x = dict["mykey"]!.integerValue 
} 

Или еще лучше, как это:

let ao : AnyObject = "howdy" 
ao.integerValue 

Пока что-то набирается как AnyObject, любые известный класс сообщения могут быть отправлены Это. Результат Swift будет безопасным. Так, например:

class Dog{} 
let d:AnyObject = Dog() 
d.integerValue // nil, because a Dog has no integerValue property