Подтвердить что ты не робот

Почему в Swift нет универсального базового класса?

В документации указано

Примечание

Классы Swift не наследуются от универсального базового класса. Классы вы определить без указания суперкласса автоматически стать базой классы для вас, чтобы вы могли опираться ".

Отрывок из: Apple Inc." Язык быстрого программирования. "iBooks.

Это не имеет большого значения для меня. Существует причина, почему Objective-C имеет универсальный базовый класс, и та же причина должна применяться к Swift, не так ли? NSObject управляет семантикой сохранения/выпуска, реализацией по умолчанию для isEqual:, hash и description. Все эти функции доступны также в Swift.

(Objective-C и Swift используют ту же среду выполнения)

Итак, что с этим? Являются ли классы Swift без определенных суперклассов только NSObject, которые представляют собой правильные корневые классы под капотом? Или это дублирование объекта по умолчанию для каждого нового корневого класса? Или они создали еще один Swift-baseclass? Реализация retain и release действительно сложна, потому что ей необходимо одновременно учитывать многопоточность и слабые ссылки.

Может быть, универсальный базовый класс в Swift (несмотря на то, что говорит документация)? Это было бы очень удобно, потому что в Objective-C я могу, например. напишите расширения, которые позволяют мне объединять вызовы методов в основной runloop, например [obj.eventually updateCounter], который может быть прочитан как "вызов -updateCounter в следующий раз, когда основная runloop получает контроль. Если, тем временем, я снова вызываю этот метод, он должен вызывается только один раз в любом случае. С помощью этого расширения можно реализовать -[UIView setNeedsDisplay] как [self.eventually display]; Это невозможно в Swift, если нет универсального базового класса (или, может быть, он знает, кто знает?)

4b9b3361

Ответ 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 в качестве корневого класса.

Ответ 2

В основном это конструктивное решение , существуют языки, которые имеют корневой класс (например, Java) и языки, которые не являются (например, С++).

Обратите внимание, что в Obj-C корневой класс не применяется. Вы можете легко создать объект, который не наследуется от какого-либо класса. Вы также можете создавать свои собственные корневые классы, в API Apple по крайней мере 3 (NSObject, NSProxy и устаревшие Object).

Причина наличия корневого класса в основном историческая - корневой класс гарантирует, что все объекты имеют некоторый общий интерфейс, некоторые общие методы (например, isEqualTo:, hash() и т.д.), которые необходимы для работы классов коллекций.

Как только у вас есть генерики (или шаблоны на С++), наличие корневого класса уже не так важно.

retain и release в NSObject больше не важны с ARC. С MRC вы все равно должны были их назвать. С ARC вы никогда не вызываете методы явно, и они могут быть реализованы более эффективно за кулисами.

В Swift методы из NSObject были разделены на протоколы - Equatable, Hashable, Printable и DebugPrintable. Это имеет то преимущество, что объекты могут совместно использовать интерфейсы с structs.

Однако ничто не мешает вам наследовать каждый класс из NSObject. Класс по-прежнему существует, и это особенно полезно, если вы имеете дело с API-интерфейсом Obj-C. В чистом Swift класс корня не нужен, хотя.

Еще одно примечание:

Классы Swift не работают поверх Obj-C; они не переводятся в Obj-C за кулисами. Они просто скомпилированы одним и тем же компилятором, который позволяет им взаимодействовать друг с другом. Это действительно важно понять. Поэтому иногда нужно добавлять @objc для обеспечения согласованности с протоколами/классами Obj-C.