Objective c ObjC:我必须在头文件中指定继承吗?

Objective c ObjC:我必须在头文件中指定继承吗?,objective-c,inheritance,Objective C,Inheritance,ObjC对象的常见示例如下(对于头文件): 是否可以避免头文件中的继承规范(即这里的B) 在我的例子中,框架A定义了类A,另一个(子)框架B定义了类B(它是NSView的子类)。A链接到B。在我的应用程序中,我链接到A,除了它是NSView的子类之外,我不需要知道关于B的任何信息。我想避免链接到B。但是如果头文件中有B,我想我无法避免它,这就是为什么我问如何避免它。否。你必须为任何子类指定超类。我可以问一下为什么要这样做吗?如果您没有在接口中指定超类,那么您的类就是根类。这意味着它不从任何其他

ObjC对象的常见示例如下(对于头文件):

是否可以避免头文件中的继承规范(即这里的
B



在我的例子中,框架A定义了类
A
,另一个(子)框架B定义了类
B
(它是
NSView
的子类)。A链接到B。在我的应用程序中,我链接到A,除了它是
NSView
的子类之外,我不需要知道关于B的任何信息。我想避免链接到B。但是如果头文件中有
B
,我想我无法避免它,这就是为什么我问如何避免它。

否。你必须为任何子类指定超类。我可以问一下为什么要这样做吗?

如果您没有在接口中指定超类,那么您的类就是根类。这意味着它不从任何其他类继承,因此它负责提供所需方法(大多数由NSObject类和协议定义的方法)的自身实现。由于这不是一项简单的任务,因此强烈建议您继承提供这些方法的其他类。

是的,您可以继承,这样您也将丢失alloc、init等的默认实现。这使您可以编写自己的alloc,NSObject中的init和其他东西

难道不能只包含从a的头本身继承的类的模拟版本吗?不确定这是否会导致问题,但这将允许您稍微清理一下链接需求。B-new可能是B'Original的一个类别

我现在有一个解决方案。我没有提供类,而是提供如下函数:

NSView* allocA();

在框架A内部,
A
B

的子类,您的应用程序将需要B的代码,因此您必须链接到B的框架,或者将B框架编译到A框架中。无论哪种方式,如果没有B的代码,就不能使用A的实例,并且必须在A的头中包含B的头。

您必须经常使用类集群解决这个问题,持有私有实现,或者创建对象工厂。然后您可以最小化模块之间的依赖关系

如果您打算使用子库,最终仍需要在某个阶段链接到该子库(例如,创建的实例)

更新-演示私有实现

私有实现可能是完全不透明的。如果您公开了它们,那么有两种方法可以实现对客户端可见的私有实现:

通过协议:

// MONDrawProtocol.h
// zero linkage required
// needs to be visible to adopt
// may be forwarded
@protocol MONDrawProtocol
- (void)drawView:(NSView *)view inRect:(NSRect)rect;
@end

// MONView.h
@protocol MONDrawProtocol;

@interface MONView : NSView
{
    NSObject<MONDrawProtocol>* drawer;
}

@end

// MONView.m

#include "MONDrawProtocol.h"

@implementation MONView

- (void)drawRect:(NSRect)rect
{
    [self.drawer drawView:self inRect:rect];
}

@end

超类属于另一个独立的(子)框架,我不需要链接到它。现在,我只链接到定义类本身的框架。@Albert:如果您使用的是在该框架中定义的类(包括在别处定义的子类,因为它们部分由它们的超类定义),那么您需要在框架中链接。这是一件有点奇怪的事情,你想要框架的功能,但你不想使用它?是你的问题,你只对课堂感兴趣,你不喜欢你必须包括所有其他的东西是框架吗?或者你想在一个框架中对一个还不可用的类进行子类化(它是由其他人开发的),在这种情况下,您可以为类创建一个临时宏,使其成为较低级别的NSObject或NSView。我想使用框架a,但不想了解框架B。请在我自己的答案中查看解决方案。我不希望它是根类。如果
NSObject
是一个超类就可以了。这只是一个例子。我把我的问题扩展了一点,让它更清楚。难道不可能重用所有的实现吗?我想要继承,我只是不想在头文件中指定它。我认为这是不可能的。我能看到的唯一方法是拥有NSObject(或任何您想要继承的类).h和.m文件的副本,并重命名为您需要的类,然后继续。在所有其他情况下,您将使用两个不同的实例,这可能不会给您期望的结果。将我自己的答案视为可能的解决方案。此解决方案不需要
B
的代码,也不需要任何到B的链接。“私有实现”是什么意思?也许这正是我想要/要求的?“请参阅我自己的答案,了解我目前的解决方案,该解决方案运行良好。”Albert更新。你的答案使用了一个工厂;工厂经常在你必须派生的时候使用,这看起来很复杂。毕竟,我仍然希望拥有
NSView
。为什么不使用我在回答中建议的东西呢?我真的看不出你的解决方案有什么好处。@Albert在某些情况下,这很有道理。苹果的框架酌情使用私有实现(如NSHTTPCookieInternal)。如果工厂在你的具体情况下工作得更好,那么就使用它。
// MONDrawProtocol.h
// zero linkage required
// needs to be visible to adopt
// may be forwarded
@protocol MONDrawProtocol
- (void)drawView:(NSView *)view inRect:(NSRect)rect;
@end

// MONView.h
@protocol MONDrawProtocol;

@interface MONView : NSView
{
    NSObject<MONDrawProtocol>* drawer;
}

@end

// MONView.m

#include "MONDrawProtocol.h"

@implementation MONView

- (void)drawRect:(NSRect)rect
{
    [self.drawer drawView:self inRect:rect];
}

@end
// MONDrawer.h
// base needs to be visible to subclass and types which use MONDrawer
// may be forwarded
@interface MONDrawer : NSObject
- (void)drawView:(NSView *)view inRect:(NSRect)rect;
@end

// MONView.h
@class MONDrawer;
@interface MONView : NSView
{
    MONDrawer * drawer;
}

@end

// MONView.m

#include "MONDrawer.h"

@implementation MONView

- (void)drawRect:(NSRect)rect
{
    [self.drawer drawView:self inRect:rect];
}

@end