Objective-C相当于类方法中Java的匿名类

时间:2022-09-07 07:37:49

I want to set the delegate of an object inside a class method in Objective-C. Pseudo-code:

我想在Objective-C中的类方法中设置对象的委托。伪代码:

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

In Java I would simply create an anonymous class that implemented the delegate protocol. How can I do something similar in Objective-C?

在Java中,我只需创建一个实现委托协议的匿名类。如何在Objective-C中做类似的事情?

Basically I would like to avoid creating a separate class (and files) to implement a simple delegate protocol.

基本上我想避免创建一个单独的类(和文件)来实现一个简单的委托协议。

3 个解决方案

#1


13  

There are currently no anonymous classes in Objective-C.

Objective-C中目前没有匿名类。

Often you can use an already existing object. For instance, for an NSTableViewDataSource, you can implement the methods in the document or view controller and pass that as the delegate.

通常,您可以使用现有对象。例如,对于NSTableViewDataSource,您可以在文档或视图控制器中实现这些方法,并将其作为委托传递。

Or you can have the object itself implement the protocol and make it its own delegate in the default case.

或者您可以让对象本身实现协议,并在默认情况下使其成为自己的委托。

Or the methods that send the delegate messages can check for a nil delegate and do something sensible in that situation.

或者发送委托消息的方法可以检查nil委托,并在那种情况下做一些合理的事情。

Or you can declare and define a class inside the implementation file you are creating the object that needs a delegate.

或者,您可以在要创建需要委托的对象的实现文件中声明和定义类。

#2


16  

As JeremyP has rightly said, There are no anonymous classes in Objective C like there are in Java.

正如JeremyP正确地说的那样,目标C中没有像Java那样的匿名类。

But in Java, anonymous classes are mostly used to implement single method interface or what we also call as a functional interface.

但在Java中,匿名类主要用于实现单个方法接口或我们也称为功能接口。

We do it to avoid having to implement the interface** in a class **just for one method implementation which is most commonly used for Listeners, Observers and event handlers.

我们这样做是为了避免必须在类**中实现接口**只是为了一个最常用于监听器,观察者和事件处理程序的方法实现。

This is mostly done because of **lack of anonymous first class functions in Java (prior to version 8 and project lambda).

这主要是因为在Java中缺少匿名的第一类函数(在版本8和项目lambda之前)。

Objective C has something called as blocks, where you can directly pass a block which contains the implementation of that single method rather than an empty class wrapping it up.

Objective C有一个叫做块的东西,你可以直接传递一个包含该单个方法实现的块,而不是一个包含它的空类。

Example:

例:

A use of Anonymous Class in Java

在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
                              }
                         });

In Objective C

在目标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
                                            }];

#3


1  

Anonymous classes can be implemented with library. Several months ago I have worked on MMMutableMethods fork to improve old implementation (discussing with author) and to add my own mechanism without any obj-c runtime manipulation.

匿名类可以用库实现。几个月前,我一直在研究MMMutableMethods fork来改进旧的实现(与作者讨论)并添加我自己的机制,而不需要任何obj-c运行时操作。

https://github.com/k06a/MMMutableMethods

https://github.com/k06a/MMMutableMethods

A. First mechanism works on obj-c runtime class creation:

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. Second mechanism works on simple message forward implementation:

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);
           }];
})

First one creates new obc-j classes in runtime, it allows you to create classes MM_CREATE_CLASS(MM_REUSE, *) and directly instances with MM_CREATE(MM_REUSE, *). Classes will be created only on first execution and reused by default, but you can avoid reusing by calling MM_CREATE_CLASS_ALWAYS(*) and MM_CREATE_ALWAYS(*).

第一个在运行时创建新的obc-j类,它允许您使用MM_CREATE(MM_REUSE,*)创建类MM_CREATE_CLASS(MM_REUSE,*)和直接实例。类将仅在第一次执行时创建并在默认情况下重用,但您可以通过调用MM_CREATE_CLASS_ALWAYS(*)和MM_CREATE_ALWAYS(*)来避免重用。

The second mechanism doesn't creates any runtime instances, just remember blocks for selectors and forward method calls to them.

第二种机制不会创建任何运行时实例,只需记住选择器的块和对它们的转发方法调用。

I prefere second way not to create a lot of classes in runtime. IMHO it is much safer and enough powerful.

我倾向于第二种方式不在运行时创建很多类。恕我直言,它更安全,更强大。

To use this library just:

要使用这个库:

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

#1


13  

There are currently no anonymous classes in Objective-C.

Objective-C中目前没有匿名类。

Often you can use an already existing object. For instance, for an NSTableViewDataSource, you can implement the methods in the document or view controller and pass that as the delegate.

通常,您可以使用现有对象。例如,对于NSTableViewDataSource,您可以在文档或视图控制器中实现这些方法,并将其作为委托传递。

Or you can have the object itself implement the protocol and make it its own delegate in the default case.

或者您可以让对象本身实现协议,并在默认情况下使其成为自己的委托。

Or the methods that send the delegate messages can check for a nil delegate and do something sensible in that situation.

或者发送委托消息的方法可以检查nil委托,并在那种情况下做一些合理的事情。

Or you can declare and define a class inside the implementation file you are creating the object that needs a delegate.

或者,您可以在要创建需要委托的对象的实现文件中声明和定义类。

#2


16  

As JeremyP has rightly said, There are no anonymous classes in Objective C like there are in Java.

正如JeremyP正确地说的那样,目标C中没有像Java那样的匿名类。

But in Java, anonymous classes are mostly used to implement single method interface or what we also call as a functional interface.

但在Java中,匿名类主要用于实现单个方法接口或我们也称为功能接口。

We do it to avoid having to implement the interface** in a class **just for one method implementation which is most commonly used for Listeners, Observers and event handlers.

我们这样做是为了避免必须在类**中实现接口**只是为了一个最常用于监听器,观察者和事件处理程序的方法实现。

This is mostly done because of **lack of anonymous first class functions in Java (prior to version 8 and project lambda).

这主要是因为在Java中缺少匿名的第一类函数(在版本8和项目lambda之前)。

Objective C has something called as blocks, where you can directly pass a block which contains the implementation of that single method rather than an empty class wrapping it up.

Objective C有一个叫做块的东西,你可以直接传递一个包含该单个方法实现的块,而不是一个包含它的空类。

Example:

例:

A use of Anonymous Class in Java

在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
                              }
                         });

In Objective C

在目标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
                                            }];

#3


1  

Anonymous classes can be implemented with library. Several months ago I have worked on MMMutableMethods fork to improve old implementation (discussing with author) and to add my own mechanism without any obj-c runtime manipulation.

匿名类可以用库实现。几个月前,我一直在研究MMMutableMethods fork来改进旧的实现(与作者讨论)并添加我自己的机制,而不需要任何obj-c运行时操作。

https://github.com/k06a/MMMutableMethods

https://github.com/k06a/MMMutableMethods

A. First mechanism works on obj-c runtime class creation:

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. Second mechanism works on simple message forward implementation:

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);
           }];
})

First one creates new obc-j classes in runtime, it allows you to create classes MM_CREATE_CLASS(MM_REUSE, *) and directly instances with MM_CREATE(MM_REUSE, *). Classes will be created only on first execution and reused by default, but you can avoid reusing by calling MM_CREATE_CLASS_ALWAYS(*) and MM_CREATE_ALWAYS(*).

第一个在运行时创建新的obc-j类,它允许您使用MM_CREATE(MM_REUSE,*)创建类MM_CREATE_CLASS(MM_REUSE,*)和直接实例。类将仅在第一次执行时创建并在默认情况下重用,但您可以通过调用MM_CREATE_CLASS_ALWAYS(*)和MM_CREATE_ALWAYS(*)来避免重用。

The second mechanism doesn't creates any runtime instances, just remember blocks for selectors and forward method calls to them.

第二种机制不会创建任何运行时实例,只需记住选择器的块和对它们的转发方法调用。

I prefere second way not to create a lot of classes in runtime. IMHO it is much safer and enough powerful.

我倾向于第二种方式不在运行时创建很多类。恕我直言,它更安全,更强大。

To use this library just:

要使用这个库:

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