Ответ 1
Существует несколько объектно-ориентированных языков, в которых можно определить новые корневые классы, включая С++, PHP и Objective-C, и они работают нормально, поэтому это определенно не особая вещь.
Существует причина, по которой Objective-C имеет универсальный базовый класс
Как сказал Султан, это неверно. В Objective-C есть несколько корневых классов, и вы можете определить новый корневой класс, просто не указав суперкласс. Как упоминал Султан, Cocoa сам имеет несколько корневых классов, NSObject
, NSProxy
и Object
(корневой класс Protocol
в ObjC 1.0).
Оригинальный язык Objective-C был очень гибким, и кто-то мог теоретически прийти и создать свой собственный корневой класс и создать свою собственную структуру, которая полностью отличается от Foundation, и использует методы, полностью отличные от retain
, release
, alloc
, dealloc
и т.д., и даже может реализовать совершенно другой способ управления памятью, если захочет. Эта гибкость является одной из таких удивительных особенностей в отношении голого языка Objective-C - она просто обеспечивает тонкий слой, все остальные вещи, такие как создание и уничтожение объектов, управление памятью и т.д., Могут быть определены пользователем рамки сверху.
Однако, с Apple Objective-C 2.0 и современным временем выполнения, больше работы нужно было сделать, чтобы создать свой собственный корневой класс. И с добавлением ARC, чтобы использовать ваши объекты в ARC, вы должны реализовать Cocoa методы управления памятью, такие как retain
и release
. Кроме того, чтобы использовать ваши объекты в коллекциях Cocoa, ваш класс должен также реализовывать такие вещи, как isEqual:
и hash
.
Итак, в современной разработке Cocoa/Cocoa Touch объекты обычно должны, по крайней мере, реализовать базовый набор методов, которые являются методами в протоколе NSObject
. Все корневые классы в Cocoa (NSObject
, NSProxy
) реализуют протокол NSObject
.
Итак, что с этим? Классы Swift без определенных суперклассы просто NSObjects, которые представляют собой правильные корневые классы в соответствии с капот? Или это дублирование объекта по умолчанию для каждого нового Корневой класс? Или они создали еще один Swift-baseclass?
Это хороший вопрос, и вы можете узнать его путем интроспекции с Objective-C временем выполнения. Все объекты в Swift в некотором смысле также являются объектами Objective-C, поскольку они могут использоваться со средой выполнения Objective-C, как и объекты из Objective-C. Некоторые члены класса (те, которые не отмечены @objc
или dynamic
), могут не отображаться в Objective-C, но в остальном все функции интроспекции во время выполнения Objective-C полностью работают на объектах с чистыми классами Swift. Классы, определенные в Swift, выглядят как любой другой класс во время выполнения Objective-C, за исключением того, что имя искажено.
Используя среду выполнения Objective-C, вы можете обнаружить, что для класса, который является корневым классом в Swift, с точки зрения Objective-C, он фактически имеет суперкласс с именем SwiftObject
. И этот класс SwiftObject
реализует методы протокола NSObject
, такие как retain
, release
, isEqual:
, respondsToSelector:
и т.д. (Хотя он фактически не соответствует протоколу NSObject
). Таким образом, без проблем можно использовать чистые объекты Swift с Cocoa API.
Однако внутри самого Swift компилятор не считает, что корневой класс Swift реализует эти методы. Поэтому, если вы определяете корневой класс Foo
, тогда, если вы попытаетесь вызвать Foo().isKindOfClass(Foo.self)
, он не будет компилировать его, жалуясь, что этот метод не существует. Но мы все равно можем использовать его с трюком - напомним, что компилятор позволит нам вызвать любой метод Objective-C (который компилятор слышал) для переменной типа AnyObject
, а поиск метода создает неявно-развернутую необязательная функция, которая преуспевает или не выполняется во время выполнения. Итак, что мы можем сделать, это нажать AnyObject
, обязательно импортировать Foundation
или ObjectiveC
(чтобы объявление было видимым компилятору), мы можем его вызвать, и он будет работать во время выполнения:
(Foo() as AnyObject).isKindOfClass(Foo.self)
В принципе, с точки зрения Objective-C класс Swift либо имеет существующий класс Objective-C как корневой класс (если он унаследован от класса Objective-C), либо имеет SwiftObject
в качестве корневого класса.