Эквивалент Objective-C анонимным классам Java в методах класса

Я хочу установить делегат объекта внутри метода класса в Objective-C. Псевдокод:

+ (ClassWithDelegate*) myStaticMethod {
    if (myObject == nil) {
        myObject = [[ClassWithDelegate alloc] init];
        // myObject.delegate = ?
    }
    return myObject;
}

В Java я бы просто создал анонимный класс, реализующий протокол делегата. Как я могу сделать что-то подобное в Objective-C?

В основном я хотел бы избежать создания отдельного класса (и файлов) для реализации простого протокола делегата.


person hpique    schedule 22.09.2010    source источник
comment
возможный дубликат реализации анонимного делегата в Objective-C?   -  person Dave DeLong    schedule 22.09.2010
comment
@Dave DeLong Уточненный заголовок, чтобы отличать его от этого вопроса. В этом случае контекст является статическим методом.   -  person hpique    schedule 22.09.2010
comment
контекст не имеет значения. Вы должны предоставить объект (id) в качестве делегата, а другой вопрос довольно четко отвечает, что в Objective-C нет такой вещи, как анонимный класс (пока), поэтому вам придется использовать обычный объект .   -  person Dave DeLong    schedule 22.09.2010
comment
В Objective-C нет статических методов. Есть сообщения экземпляра и сообщения класса.   -  person JeremyP    schedule 22.09.2010
comment
@Dave DeLong Скорее всего, мой вопрос плохо сформулирован, но я не вижу в них один и тот же вопрос. Да, в Obj-C нет анонимных классов. Но мой вопрос: как лучше всего делать в сообщениях класса Obj-C, какие анонимные классы позволяют мне делать в статических методах Java?   -  person hpique    schedule 22.09.2010


Ответы (3)


В настоящее время в Objective-C нет анонимных классов.

Часто можно использовать уже существующий объект. Например, для NSTableViewDataSource вы можете реализовать методы в документе или контроллере представления и передать их в качестве делегата.

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

Или методы, которые отправляют сообщения делегата, могут проверить делегата с нулевым значением и сделать что-то разумное в этой ситуации.

Или вы можете объявить и определить класс внутри файла реализации, вы создаете объект, которому нужен делегат.

person JeremyP    schedule 22.09.2010
comment
Спасибо ДжеремиП! Таким образом, в основном в этом случае я мог бы определить специальный класс в файле реализации, создать экземпляр в сообщении класса и назначить его делегатом. Это было бы правильно? - person hpique; 22.09.2010

Как правильно сказал JeremyP, в Objective C нет анонимных классов, как в Java.

Но в Java анонимные классы в основном используются для реализации интерфейса с одним методом или того, что мы также называем функциональным интерфейсом.

Мы делаем это, чтобы не реализовывать интерфейс ** в классе ** только для реализации одного метода, который чаще всего используется для прослушивателей, наблюдателей и обработчиков событий.

В основном это делается из-за **отсутствия анонимных функций первого класса в Java (до версии 8 и лямбда-выражения проекта).

В Objective C есть что-то, называемое блоками, где вы можете напрямую передать блок, содержащий реализацию этого единственного метода, а не пустой класс, обертывающий его.

Пример:

Использование анонимного класса в Java

//Functional interface
interface SomethingHandler 
{
  void handle(Object argument);
}

//a method that accepts the handler in some other class
class SomeOtherClass
{ 
  void doSomethingWithCompletionHandler(SomethingHandler h){
      // do the work that may consume some time in a separate thread may be.
      // when work is done call the handler with the result which could be any object
      h.handler(result);
  };
}

// Somewhere else in some other class, in some other code
// passing the handler after instantiating someObj as an object of SomeOtherClass which can use the handler as needed
SomeOtherClass someObj = new SomeOtherClass();
someObj.doSomethingWithCompletionHandler( new SomethingHandler()
                        {
                              void handle(Object argument)
                              {
                                // handle the event using the argument
                              }
                         });

В задаче C

// declare the handler block 
typedef void (^SomethingHandler)(id argument){}

// this interface is different than Java interface  which are similar to Protocols
@interface SomeOtherClass
 -(void)doSomethingWithCompletionHandler:(SomethingHandler)h;
@end

@implementation SomeOtherClass
 -(void)doSomethingWithCompletionHandler:(SomethingHandler)h
 {
          // do the work that may consume some time in a separate thread may be.
          // when work is done call the handler with the result which could be any object
          h(result);
 }

@end

  // passing the handler after instantiating someObj as an object of SomeOtherClass which can use the handler as needed

SomeOtherClass* someObj = [[SomeOtherClass alloc] init]; // ARC :)

[someObj doSomethingWithCompletionHandler:^(id argument)
                                            {
                                               // handle the event using the argument
                                            }];
person Amogh Talpallikar    schedule 16.07.2013

Анонимные классы могут быть реализованы с помощью библиотеки. Несколько месяцев назад я работал над вилкой MMMutableMethods, чтобы улучшить старую реализацию (обсуждаем с автором) и добавить свой собственный механизм без каких-либо манипуляций во время выполнения obj-c.

https://github.com/k06a/MMMutableMethods

A. Первый механизм работает при создании класса времени выполнения obj-c:

MM_CREATE(MM_REUSE,^(Class class){
    [class addMethod:@selector(onResultWithId:)
        fromProtocol:@protocol(AMCommandCallback)
            blockImp:^(id this,id res){
                NSLog(@"onResultWithId: %@",res);
            }];
    [class addMethod:@selector(onErrorWithJavaLangException:)
        fromProtocol:@protocol(AMCommandCallback)
            blockImp:^(id this,JavaLangException *e){
                NSLog(@"onErrorWithJavaLangException: %@",e);
            }];
})

B. Второй механизм работает с простой реализацией пересылки сообщений:

MM_ANON(^(MMAnonymousClass *anon){
    [anon addMethod:@selector(onResultWithId:)
       fromProtocol:@protocol(AMCommandCallback)
           blockImp:^(id this,id res){
               NSLog(@"onResultWithId: %@",res);
           }];
    [anon addMethod:@selector(onErrorWithJavaLangException:)
       fromProtocol:@protocol(AMCommandCallback)
           blockImp:^(id this,JavaLangException *e){
               NSLog(@"onErrorWithJavaLangException: %@",e);
           }];
})

Первый создает новые классы obc-j во время выполнения, он позволяет создавать классы MM_CREATE_CLASS(MM_REUSE, *) и непосредственно экземпляры с MM_CREATE(MM_REUSE, *). Классы будут созданы только при первом выполнении и повторно использованы по умолчанию, но вы можете избежать повторного использования, вызвав MM_CREATE_CLASS_ALWAYS(*) и MM_CREATE_ALWAYS(*).

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

Я предпочитаю второй способ не создавать много классов во время выполнения. ИМХО намного безопаснее и достаточно мощнее.

Чтобы использовать эту библиотеку просто:

pod 'MMMutableMethods', :git => 'https://github.com/k06a/MMMutableMethods'
person k06a    schedule 13.10.2015