id подтверждает протокол, но где будет реализация? - PullRequest
5 голосов
/ 03 октября 2011

Это, наверное, наивный вопрос, но я чувствую себя немного потерянным. Я прочитал руководство по iOS для протоколов на Apple Documentation , но не совсем имело смысл. Позвольте мне объяснить мою дилемму в кратчайшие сроки.

Допустим, у меня есть протокол, как показано ниже,

@protocol MyProtocol<NSObject>
- (void)someMessage;
@end

И чем в моем коде я объявляю переменную, подобную этой,

id<MyProtocol> someVar;

Пока все хорошо, но someVar - это тип идентификатора, поэтому мы будем реализовывать -(void) someMessage;?

<ч />

ПРИМЕЧАНИЕ: У меня есть знания, такие как, Реализация определенных функции интерфейса должны быть внутри класса, который реализует это интерфейс. Это понимание от Java, так и в Java это очень очевидно знать, какой объект от какого класса и какой интерфейс этот класс реализует. Но выше Objective C путь меня просто смутил: (.

<ч />

Ответы [ 4 ]

7 голосов
/ 03 октября 2011

Когда вы пишете:

id<MyProtocol> someVar

, вы просто указываете, что someVar будет объектом любого класса, но этот класс будет соответствовать протоколу MyProtocol.

Так чтобудет некоторой точкой в ​​вашем коде, которая будет создавать экземпляр someVar.На этом этапе someVar будет связан с классом.Этот класс должен удовлетворять протоколу MyObject.Обратите внимание, что компилятор сделает все возможное, чтобы предупредить вас в случае возникновения проблем, например, если вы приведете этот объект к какому-либо классу, который не уважает протокол, например, предположим, что ваш протокол определяет метод с именем «protocolMethod», то:

[(NSArray *)someVar protocolMethod]

сгенерирует предупреждение компилятора («NSArray может не отвечать на protocolMethod»).

Конечно, вы никогда не будете защищены от ошибок во время выполнения: так что если во время выполнения вы создадите someVar для классаэто не удовлетворяет протоколу, тогда любые вызовы методов протокола вызовут исключение.

5 голосов
/ 03 октября 2011

Протоколы Objective-C слабо похожи на интерфейсы Java в терминах концепций и кода, проще говоря.

Если вы объявляете переменную Java типа интерфейса, это означает, что она может приниматьлюбой объект, который реализует этот интерфейс.В Objective-C переменная id означает любой тип указателя, поэтому id<MyProtocol> означает любой указатель на объект, который принимает MyProtocol и в этом смысле похож на объявление типа интерфейса Java.

В Java вы реализуете интерфейсный метод в классе и объявляете этот класс для реализации интерфейса.Точно так же в Objective-C вы реализуете метод протокола в классе, и этот класс принимает протокол.

Вот сравнение кода между Java и Objective-C (опять же, это просто слабое сравнение двух похожихпонятия):

Java

public interface MyInterface {
    void someMethod();
}

public class MyClass implements MyInterface {
    public void someMethod() {
        System.out.println("Some method was called");
    }
}

public class Main {
    public static void main(String[] args) {
        // Any class that implements MyInterface can be
        // assigned to this variable
        MyInterface someVar = new MyClass();
        someVar.someMethod();
    }
}

Объективно-C

@protocol MyProtocol <NSObject>
- (void)someMessage;
@end

@interface MyClass : NSObject <MyProtocol>
- (void)someMessage;
@end

@implementation MyClass

- (void)someMessage {
    NSLog(@"Some message was sent");
}

@end

int main(int argc, const char *argv[]) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    // Any class that adopts MyProtocol can be
    // assigned to this variable
    id<MyProtocol> someVar = [[MyClass alloc] init];
    [someVar someMessage];

    [someVar release];
    [pool drain];
    return 0;
}
4 голосов
/ 03 октября 2011

Вам необходимо реализовать класс, который реализует методы в протоколе например,

@interface MyObject: NSObject <NyProtocol>
- (void)someMessage;
@end

и

@implementation MyObject
-(void)someMessage()
{
  printf(@"a message");  ...
}
@end

А затем используйте это как

someVar = [MyObiect alloc]......

Вы также можете реализовать метод как категорию в NSObject, доступную для всех классов.

См. Принятие протокола от яблок Концептуальный документ цели C

0 голосов
/ 22 октября 2013

Я написал категорию для NSObject - StrictProtocols - которая решает эту "проблему". Он реализует следующие методы ...

/* "non" doesn't implement ANY of the declared methods! */
[non implementsProtocol:proto];         -> NO;
[non implementsFullProtocol:proto];     -> NO;

/* "semi" doesn't implement the @optional methods */
[semi implementsProtocol:proto];        -> YES;
[semi implementsFullProtocol:proto];    -> NO;  

/* "strict" implements ALL, ie the @optional, @required, and the "unspecified" methods */
[strict implementsProtocol:proto];      -> YES;
[strict implementsFullProtocol:proto];  -> YES; 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...