Строительство "Класс""объявление переменной в Objective-C - PullRequest
2 голосов
/ 23 марта 2011

Мне просто интересно, возможно ли объявление переменной способом, известным из Java, в Objective-C:

Class<?extends SomeType>

Например: у меня есть класс с именем MyClass.Он имеет статический метод

+ (void)myMethod

Он также имеет два подкласса: MySubclassA и MySubclassB.У меня есть такой код:

Class myClass;
if(<some condition>) {
  myClass = [MySubclassA class];
} else {
  myClass = [MySubclassB class];
}
[myClass myMethod];

Этот код работает нормально, предупреждений компилятора нет, но мне просто интересно, присутствует ли упомянутая мной конструкция в Objective-C.

Спасибо!

1 Ответ

1 голос
/ 23 марта 2011

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.

...