Objective-C не имеет шаблонов (например, C ++) или универсальных типов со стиранием типов (например, Java) или универсальных типов во время выполнения (например, C #).В отличие от этих языков, сообщения Objective-C динамически отправляются во время выполнения (вместо привязки во время компиляции).Таким образом, многие системы для создания независимого от типа кода в C ++, Java или C # не нужны.Objective-C предпочитает «типизацию утки», при которой любой объект, который отвечает на данный селектор (сообщение), может получить это сообщение посредством вызова кода, независимо от типа принимающего объекта.Так как классы являются объектами в Objective-C, то же самое верно и для методов класса, как и для методов экземпляра.
Таким образом, данный
@interface MyClassA : NSObject
{}
- (void)someMethod;
@end
@interface MyClassB: NSObject
{}
- (void)someMethod;
@end
вызывающий код может выглядеть следующим образом
- (void)someOtherMethodInAnOtherClassWithObject:(id)obj
{
[obj someMethod];
}
Этот код будет компилироваться и нормально работать во время выполнения, предполагая, что obj
это или экземпляр MyClassA
или MyClassB
.
Конечно, хорошая практика будетдиктуйте, что вы определяете @protocol
в этой ситуации:
@protocol MyProtocol
- (void)myMethod
@end
и объявляете, что ваши MyClassA
и MyClassB
оба реализуют протокол MyProtocol
.Ваш вызывающий код будет выглядеть как
- (void)someOtherMethodInAnOtherClassWithObject:(id<MyProtocol>)obj
{
[obj someMethod];
}
, а компилятор выдаст вам предупреждение / ошибку (в зависимости от флагов -W), если вы попытаетесь вызвать someOtherMethodInAnOtherClassWithObject:
, передавая объект типа, который нене реализует интерфейс MyProtocol
.
Обратите внимание, что id<MyProtocol>
является , а не универсальным типом, это экземпляр типа id
, который, как вы утверждаете, реализует протокол MyProtocol
,Также обратите внимание, что первая версия клиентского кода работает просто отлично, потому что все, что действительно важно, это то, может ли obj
ответить на селектор -myMethod
.