Objective-C 在类方法中等同于 Java 的匿名类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3770359/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 03:17:50  来源:igfitidea点击:

Objective-C equivalent to Java's anonymous classes in class methods

javaobjective-cdelegatesanonymous-types

提问by hpique

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.

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

采纳答案by JeremyP

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.

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

回答by Amogh Talpallikar

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

正如 JeremyP 所说的那样,Objective 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.

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

回答by k06a

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

匿名类可以用库来实现。几个月前,我在MMMutableMethodsfork 上工作以改进旧的实现(与作者讨论)并添加我自己的机制,而无需任何 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_CLASS(MM_REUSE, *)并直接使用MM_CREATE(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'