代码之家  ›  专栏  ›  技术社区  ›  user187291

是否可以有“仅实现”类成员?

  •  5
  • user187291  · 技术社区  · 14 年前

    这是一个初学者的问题,所以请耐心听我说。

    我有一个使用第三方库的类(Onigurma,如果这很重要的话)。我希望库方法完全由我自己修饰,这样我就可以随时切换类的底层实现。类似:

    // MyClass.h
    
    @interface MyClass : NSObject ...
    
    - (int) doSomething;
    
    
    // MyClass.m
    
    #import "some_library.h"
    
    @implementation MyClass
    
    - (int) doSomething 
    {
       //call library's specific stuff
    }
    

    到目前为止,还不错,但是现在我需要在myclass中使用一个实例变量,该变量有一些库定义的类型(在“some-library.h”中声明的结构)。当然,我可以在界面部分导入库:

    //MyClass.h
    
    #import "some_library.h"
    
    @interface MyClass : NSObject {
        some_library_t blah;
    }
    - (int) doSomething;
    @end
    

    但这正是我试图避免的——让MyClass的用户知道它的实现细节。

    我可以从我的类的接口中“隐藏”特定于库的类型吗?标准做法是什么?

    3 回复  |  直到 12 年前
        1
  •  8
  •   Georg Fritzsche    14 年前

    标准做法是使用 opaque pointers 到库类型或自定义 实施 结构 平普尔 - 指向实现的指针 )

    要做到这一点,您必须知道可以定义指向不完整类型的指针,即只声明存在的类型。例如。:

    struct FooImpl;
    
    @interface Foo {
        struct FooImpl* impl; // using pointer is ok for incomplete types
    }        
    @end
    

    然后可以在实现文件中定义类型:

    struct FooImpl {
        // ... member definition
    };
    

    并分配/初始化它,例如 -(id)init 方法。

    FooImpl 也可以 SomeLibraryType 如果库类型是一个结构,那么您将以相同的方式向前声明它,并将库头包含在源文件中,这将为您提供结构定义。

        2
  •  3
  •   bbum    14 年前

    GF的回答是不切实际的,但也有另一种方式。使用不透明类。

    福:

    @interface Foo : NSObject
    {
        id internalGunk;
    }
    @end
    

    福:

    #import "Foo.h"
    
    @interface PrivateStuff:NSObject
    ... declare ivars and/or properties and/or methods here ...
    @end
    
    @implementation PrivateStuff
    ... any custom implementation and/or @synthesizes here ...
    @end
    
    #define SELF_PRIVVY ((PrivateStuff *)internalGunk)
    @implementation Foo
    ... implementation here ...
    @end
    

    如果你不喜欢自己,你可以这样做:

    // in Foo's @implementation
    - (PrivateStuff *) privateStuff { return internalGunk; }
    

    上面的模式(全部)有几个优点。首先,它与GC完全兼容,因为所有内容都声明为对象引用。其次,如果需要的话,将私有的东西重构成一个单独的类要容易得多。最后,有了这个类来保存私有空间,就可以更容易地将与私有内容相关的任何逻辑或持久性与其他所有内容分离出来;这将使未来的重构更加容易。

    是否是更好的解决方案来满足您的需求取决于您的具体需求。

        3
  •  0
  •   Community holdenweb    7 年前

    我了解到,自从llvm 3.0以来,您可以将接口的花括号部分(声明ivars的部分)移动到实现(.m文件,位于@implementation块内)

    来源: http://www.raywenderlich.com/5773/beginning-arc-in-ios-5-tutorial-part-2

    (链接是一个弧教程,但此新功能独立于弧)。

    就我个人而言,我既惊讶又高兴。

    编辑:原来是从xcode 4.2开始的:

    What's the difference between adding pseudo-private ivars in a class extension or in the @implementation block?