Массив, хранящий объекты Any, также имеет тип AnyObject.

let f: () -> Void = { }

let array = ["a", 1, false, f] as [Any]

if array[3] is AnyObject {
  print(array[3])
}

Почему элемент оценивается как true для AnyObject, даже если массив настроен на хранение Any?

Почему функция принимает значение true как AnyObject, хотя AnyObject по определению может быть только классом?

В качестве другого примера:

let f: () -> Bool = { return true }
let ff = f as AnyObject
(ff as () -> Bool)()

Это противоречит определению AnyObject в документе по API, в котором говорится, что:

AnyObject можно использовать в качестве конкретного типа для экземпляра любого класса, типа класса или протокола только для класса.

или официальное Руководство по языку программирования Swift:

• Any может представлять экземпляр любого типа, включая типы функций.

• AnyObject может представлять экземпляр любого типа класса.

В приведенном выше примере функция может быть представлена ​​как AnyObject.

В другом месте в SO есть объяснение (как указано @hamish), что внутри, поскольку используется класс SwiftValue, все можно связать с AnyObject. Логика объяснения кажется ошибочной/обратной, поскольку мы должны привести реализацию в соответствие с определением языка, а не наоборот, поэтому либо реализация неверна, либо определение AnyObject и оператора проверки типов неверно?


person Boon    schedule 14.02.2017    source источник
comment
Потому что все можно подключить к AnyObject в Swift 3. См. AnyObject не работает в Xcode8 beta6?   -  person Hamish    schedule 14.02.2017
comment
Почему и как функция подключается к AnyObject? Разве это не нарушает определение AnyObject? Такое поведение кажется неправильным, даже если оно возможно.   -  person Boon    schedule 14.02.2017
comment
Прочитайте связанные вопросы и ответы — вещи, которые напрямую несовместимы с Obj-C, помещаются в коробку, совместимую с Objc-C, _SwiftValue. Причина этого в том, что id теперь подключен к Swift как Any, поэтому Any необходимо подключить обратно к id.   -  person Hamish    schedule 15.02.2017
comment
Я могу понять, что применение между id и Any. Но почему AnyObject?   -  person Boon    schedule 15.02.2017
comment
Поскольку _SwiftValue — это класс (должен быть, чтобы быть совместимым с Obj-C), и, следовательно, является AnyObject.   -  person Hamish    schedule 15.02.2017
comment
Я понимаю объяснение, но не логику. Почему что-то вроде приведения is требует объяснения внутреннего поведения реализации, чтобы оправдать такое поведение? Разве поведение не должно быть определено на уровне языка, а внутренняя реализация должна соответствовать ему?   -  person Boon    schedule 15.02.2017
comment
В общих чертах, возможно, но я бы не согласился с Any и AnyObject. Если вы широко используете эти типы, вы либо работаете с Cocoa (что является временной и улучшающейся ситуацией), либо, вероятно, делаете что-то не так. В Swift следует избегать таких типов, как [Any]. Но когда приходится иметь дело с Cocoa, имеет смысл сделать его максимально удобным и прозрачным (мостовым).   -  person Rob Napier    schedule 15.02.2017
comment
@RobNapier Большинство определений, которые я видел в отношении AnyObject и оператора проверки типа, кажутся неполными / неточными в отношении фактического поведения AnyObject. Например, в документе API говорится, что AnyObject можно использовать в качестве конкретного типа для экземпляра любого класса, типа класса или протокола только для класса. Это кажется грубо вводящим в заблуждение, поскольку поведение в этом посте никоим образом не подразумевается.   -  person Boon    schedule 15.02.2017
comment
Я предполагаю, что вы импортировали Foundation, правильно? Это изменяет поведение AnyObject. Я не говорю, что это задокументировано, я говорю, что AnyObject — это глубокая трясина безумия, которую, если она вам не нужна для соединения с Cocoa, вам, вероятно, не следует использовать в любом случае, и, вероятно, в будущем она изменится каким-то странным образом. иногда какая-то функция делает переход к Cocoa более полезным. Я не защищаю Swift в этом, как это обычно бывает.   -  person Rob Napier    schedule 15.02.2017
comment
@RobNapier не импортировал Foundation. Я думал, что неявное преобразование моста было устранено, чтобы избежать путаницы. Какое другое поведение будет создавать import Foundation для AnyObject? Кстати, я привел пример приведения функции к AnyObject, хотя по определению он принадлежит к области Any.   -  person Boon    schedule 15.02.2017
comment
Я не понимаю, куда ты клонишь со всем этим. Если вы считаете, что документы неверны, откройте дефект (bugs.swift.org). Есть ли здесь актуальный вопрос? Да, есть бокс. Да, AnyObject соединяет способами, которые не совсем соответствуют тексту, который вы цитируете. Swift не полностью определен его документами. Если есть конфликт, откройте дефект, но я не думаю, что здесь есть вопрос о переполнении стека.   -  person Rob Napier    schedule 15.02.2017
comment
@RobNapier У меня были проблемы с пониманием поведения и определения в руководстве по программированию. Фактический вопрос заключается в том, почему AnyObject ведет себя почти как Any, хотя в документе говорится об обратном. Как бы вы перефразировали определение AnyObject vs Any (как в настоящее время определено в языке программирования Swift), если бы вы его написали? Буду рад принять это как ответ на этот пост.   -  person Boon    schedule 15.02.2017


Ответы (1)


Во-первых, руководство по языку программирования Swift не является спецификацией языка в том смысле, в каком ISO 9899 определяет C. (И даже при наличии стандарта ISO не каждый компилятор реализует C идентично или даже в 100% соответствии со стандартом.) Если вы найти несоответствие между компилятором и документацией, скорее всего, это ошибка документации, как и ошибка компилятора.

Тем не менее, я считаю, что вы упустили из виду важную часть спецификации, на которую вы ссылаетесь:

AnyObject также можно использовать в качестве конкретного типа для экземпляра типа, который связывается с классом Objective-C. Многие типы значений в Swift соединяются с аналогами Objective-C, такими как String и Int.

() -> Void эквивалентен dispatch_block_t, который соединяется с ObjC как dispatch_object (см. dispatch/object.h и os/object.h):

/*
 * By default, dispatch objects are declared as Objective-C types when building
 * with an Objective-C compiler. This allows them to participate in ARC, in RR
 * management by the Blocks runtime and in leaks checking by the static
 * analyzer, and enables them to be added to Cocoa collections.
 * See <os/object.h> for details.
 */
OS_OBJECT_DECL_CLASS(dispatch_object);

Так что нет ничего удивительного в том, что () -> Void можно превратить в AnyObject.

На практике практически все теперь может соединяться с AnyObject (опять же, с точки зрения спецификации языка, все, что может быть NSValue, может быть AnyObject, хотя это не совсем так, как это реализовано).

Однако AnyObject отличается от Any. Any ведет себя как протокол (несмотря на то, что это не протокол). AnyObject ведет себя как суперкласс любого класса (несмотря на то, что на самом деле это протокол).

let b = true                         // true
let bany = true as Any               // true
let banyobj = true as AnyObject      // 1 <=== (because it's NSNumber)

MemoryLayout.size(ofValue: b)        // 1 (size of a bool)
MemoryLayout.size(ofValue: bany)     // 32 (size of a protocol box)
MemoryLayout.size(ofValue: banyobj)  // 8 (size of a reference pointer)

type(of: b)                          // Bool.Type
type(of: bany)                       // Bool.Type
type(of: banyobj)                    // __NSCFBoolean.Type

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

Разумно открыть дефект в документах AnyObject, чтобы включить более подробное объяснение того, что любой тип может быть преобразован в ссылочный тип с помощью as AnyObject, но это просто упущение, а не противоречие тому, что уже есть. (И если это противоречие или вы находите это запутанным, опять же, правильный ответ — открыть дефект, чтобы улучшить документы, чтобы они соответствовали Swift, а не Swift, чтобы они соответствовали документам.)

person Rob Napier    schedule 15.02.2017