Почему целые числа не соответствуют протоколу AnyObject?
Почему у меня есть массив [AnyObject]
и помещаем в него кучу разных размеров...
var a = [AnyObject]()
a.append(Int(1))
a.append(Float64(3.14))
a.append(Bool(true))
... кроме Int32
и Int64
....
a.append(Int32(1)) // err: type 'Int32' does not conform to protocol 'AnyObject'
a.append(Int64(1)) // err: type 'Int64' does not conform to protocol 'AnyObject'
В документации для AnyObject
указано:
"AnyObject может представлять экземпляр любого типа класса"
Но когда я нажимаю команды на Int
, Int32
или Int64
, чтобы увидеть стандартное определение библиотеки этих типов, я вижу, что все они являются значениями struct
.
В чем проблема? Почему это выглядит так?
Ответы
Ответ 1
В Swift есть два типа любых типов: Any
, которые могут действительно удерживать что угодно - структуру, перечисление или класс и AnyObject
, которые могут содержать только классы.
Причина, по которой кажется, что AnyObject
может содержать структуры, иногда заключается в том, что некоторые конкретные типы неявно преобразуются в их NSEquivalent для вас по мере необходимости, чтобы сделать Objective-C interop менее болезненным.
Когда вы пишете let ao: AnyObject = Int(1)
, он действительно не помещает Int
в AnyObject
. Вместо этого он неявно преобразовывает ваш Int
в NSNumber
, который является классом, а затем помещает его.
Но только некоторые типы имеют это неявное преобразование. Int
, но Int32
doesnt, следовательно, это поведение:
// fine
let aoInt: AnyObject = Int(1) as NSNumber
// also fine: implicit conversion
let aoImplicitInt: AnyObject = Int(1)
// not fine: error: 'Int32' is not convertible to 'NSNumber'
let aoInt32: AnyObject = Int32(1) as NSNumber
// but the implicit error is less, ahem, explicit
// error: type 'Int32' does not conform to protocol 'AnyObject'
let aoImplicitInt32: AnyObject = Int32(1)
Можно утверждать, что для смазывания колес должно быть больше неявных преобразований, но опять же, эти неявные преобразования уже являются источником большой путаницы, а направление в последней бета-версии состоит в том, чтобы иметь меньше, а не больше.
Ответ 2
Протокол, который дает Int и др. эту способность, является _ObjectiveCBridgeable, который вы можете принять самостоятельно, если вы чувствуете себя авантюрно.
Ответ 3
Потому что Int - тип значения.
AnyObject относится к типам ссылок (классы), а не типам значений
Любые относятся к типам ссылок + типам значений (structs + classes)
Вы должны использовать Any для valueTypes, а не AnyObject
Типы значений > обычно structs, enums, bla bla..
Типы ссылок > обычно классы
Существует два типа переменных > Типы ссылок и типы значений
Типы ссылок являются типами указателей и обычно содержат значение адресного табло, в котором хранятся исходные данные.
Типы значений не являются адресами. Они содержат прямое значение
Int asd = 3 (asd непосредственно содержит 3)
Int, Float, типы номеров... Дата почти всегда struct (тип значения) на большинстве языков компьютера.
Строка почти всегда является гибридом на большинстве компьютерных языков
ViewControllers, Views, Buttons,... arrays, словари,... и ваши пользовательские определенные классы являются типами ссылок