不调用init就可以创建Objective-C子类吗

不调用init就可以创建Objective-C子类吗,objective-c,inheritance,Objective C,Inheritance,我使用的是一个第三方库,它不公开它的init方法,并且从类级别的消息中执行一些特殊的我不知道的事情。这是否禁止我进行子类化 我制作了一个测试用例(启用了ARC) A.h 上午 B.h 假设我不能直接调用A的initWithAbar:,我在子类化A时有什么选择吗?如果A的aWithBar调用A的init,init有什么特别之处?注意: -[NSObject init]仍然可用。如果类的创建者很小心,他们已经重写了init,因此它使用默认参数调用initWithBar: 如果您使用运行时内省或类转

我使用的是一个第三方库,它不公开它的init方法,并且从类级别的消息中执行一些特殊的我不知道的事情。这是否禁止我进行子类化

我制作了一个测试用例(启用了ARC)

A.h

上午

B.h

假设我不能直接调用A的
initWithAbar:
,我在子类化A时有什么选择吗?如果A的aWithBar调用A的init,init有什么特别之处?

注意:

  • -[NSObject init]
    仍然可用。如果类的创建者很小心,他们已经重写了
    init
    ,因此它使用默认参数调用
    initWithBar:

  • 如果您使用运行时内省或
    类转储
    查找类
    A
    上的方法列表,那么确实可以声明(可能在类别中)并调用
    -[A initWithBar:

  • 但如果你不想做这些(特别是#2,因为这是一个黑客),那么为什么不创建一个类似的方便方法呢?大概是这样的:



请再次注意,只有当开发人员注意并使用
[self initWithBar:
实现
aWithBar:
时,这才有效。如果类名是硬编码的(如您的示例中所示),那么您无法通过调用便利方法获得
B
的实例。

该实例仍然是类A。发送给B的消息在您的第三个解决方案中似乎不起作用。上面写着无法识别的选择器。@huggie看到了答案中的最后一个通知。开发人员没有注意到,你基本上没有其他选择。谢谢,明白了。我想我会改做封装。谢谢。您上次的通知是指[[self-alloc]initWithBar:]吗?我在Xcode 4.6上试过,它仍然会说它是类A(通过NSLogging[A_实例类])。奇怪的是,我在Xcode 5和iOS 7上尝试了它,两种情况都返回类B。运行时似乎有了变化。我在几个月前进行了投票,但当时我没有任何问题。但现在我又一次绊倒了,我很好奇。你解决了这个问题吗?下面的答案对你有用吗?如果你能分享你的结果,那就太好了。提前谢谢。我没有尝试类转储解决方案。我也无法找到第一个或第三个解决方案。这可能是由于最初的库开发人员“不小心”。最后我选择了作文,谢谢你的回复。有趣的是,这句台词的“不小心”听起来似乎很“好”。它需要破译。我说得对吗?换句话说,如果他重写
init
并调用
self
,那么它是可行的,如果不是,它是可撤销的?你介意分享一下复合版本吗?这是否有点像将类
C
与类
A
(来自框架)和类
B
组合在一起?有一个好的。组合只是意味着将类a对象作为类B对象的成员变量,我只是将消息转发给B到a。当然,这意味着类B不再是a的子类。这可能会破坏依赖于继承的代码。
@interface A : NSObject 
@property (nonatomic, strong) NSString * bar;
-(id) initWithAbar:(NSString *) bar;
+(id) aWithBar:(NSString *) bar;
@end
#import "A.h"
@implementation A
-(id) initWithAbar:(NSString *) bar
{
    self = [super init];
    if (self) {
        self.bar = bar;
    }
    return self;
}


+(id) aWithBar:(NSString *) bar
{
    return [[A alloc] initWithAbar:bar];
}

@end
#import <Foundation/Foundation.h>
#import "A.h"

@interface B : A
@property (nonatomic, strong) NSString *foo;
-(id) initWithFoo:(NSString *)foo bar:(NSString *)bar;
@end
#import "B.h"

@implementation B

-(id) initWithFoo:(NSString *)foo bar:(NSString *)bar
{
    self = (B*)[A aWithBar:bar]; // Still actually A, knew that by printing [self class];
    if (self) {
        self.foo = foo; // Error: unrecognized selector here
    }
    return self;
}

@end
@implementation B

+ (B *)beeWithBar:(NSString *)bar
{
    B *instance = [self aWithBar:bar];
    instance.someOtherProperty = 42;
    return instance;
}

@end