是否可以使用在实现文件中添加的扩展方法而不是 objective c 中的接口文件?

Is it possible to use extension methods which are added at implementation file rather than interface file in objective c?

这是headerfile/Interface文件(className.h). 这里 printSomething 方法被声明为扩展。我稍后会在 main.m

中调用它

extension.h

#import <Foundation/Foundation.h>

@interface extension_class : NSObject

@end


@interface extension_class ()       // This is the external method which is added using extension
- (void) printSomething;
@end

这是实现文件(className.m)。这里定义了printSomething方法。

extension.m

        #import "extensions.h"
        
        @implementation extension_class
        
        - (void) printSomething
        {
            NSLog(@"I'm the method defined inside extension class but declared by using extensions");
        }
        @end
    

到目前为止一切正常。现在我的问题很简单,为什么我不能访问 printSomething 方法,如果我在实现文件中声明(直到现在声明和定义没有在同一个文件中完成)它。如下面的代码片段? (请对比观察上面两个.h和.m文件与下面两个文件的变化,才能明白我的意思)

extension.h

#import <Foundation/Foundation.h>
        
        @interface extension_class : NSObject
        
        @end
    
    

extension.m

    #import "extensions.h"
    
    @interface extension_class ()       // This is the external method which is added using extension
    - (void) printSomething;
    @end

    @implementation extension_class
    - (void) printSomething
    {
        NSLog(@"I'm the method defined inside extension class but declared by using extensions");
    }
    @end

这是两种情况下通用的主要方法。

main.m

#import "extensions.h"
int main()
{
    @autoreleasepool
    {
        extension_class *object = [[extension_class alloc]init];
        [object printSomething];
    }
    return 'O';
}

如果 objective C 不允许我们在任何我们喜欢的地方添加方法,那么在 objective C 中进行扩展有什么意义呢?或者有没有其他方法可以实现我上面说的?

您可以在 .m 文件中自由定义扩展名。这是非常普遍的。这些扩展通常不会为 .h 文件的导入者所知,因此它们不会轻易从其他文件中调用。这是好事。它让我们可以进行“私人”扩展,这是非常有用和常见的。

他们并不是真正的私人。任何东西都可以调用 ObjC 中的任何东西。外部呼叫者只是不知道该方法。但是他们可以将方法自己声明为一个类别(注意括号内的文本)并调用它:

OtherClass.m

#import "ExtensionClass.h"

@interface ExtensionClass (ThingsIKnowYouHave)
- (void) printSomething;
@end

...

[extensionClass printSomething];

或者他们当然可以直接调用它而不声明它(尽管这可能会导致 ARC 问题,所以在现代 ObjC 中避免这种情况):

[(id)extensionClass printSomething];

或者他们可以将其称为选择器(同样,这会导致 ARC 问题;因此最好使用类别):

[extensionClass performSelector: NSSelectorFromString(@"printSomething")];

在头文件中创建扩展(即“public”扩展)确实没有多大意义。如果它在头文件中,你还不如把它放在接口中。扩展的最常见用途(基本上就是发明它们的原因)是您可以在实现文件中定义方法。

不应将扩展与类别混淆,类别是括号内的文本。创建它们是为了帮助组织大型 classes,后来在添加 @optional 之前用于“非正式协议”。扩展可以直接向基础添加方法 class。类别接口只是说“这个方法可能存在”。扩展接口是主要接口的形式延续(编译器要求它们被实现)。

有关类别和扩展的更多信息,请参阅同一指南中的 Customizing Existing Classes in the Programming with Objective-C guide. See also Defining Classes,这可能会消除一些我相信您对头文件和接口的困惑。