类实例化而不在所有构造函数中调用super

时间:2013-07-11 18:47:34

标签: ios inheritance constructor initialization

我有以下情况: 我正在延长UITextView control (MyTextView : UITextView)。根据运行时设备版本,我有不同的实现。所以目前我在MyTextView类的实现中有很多“if-else”语句。

为了使其更易于维护,我想将其拆分为不同的类:

MyTextViewIos5 : MyTextViewMyTextViewIos6:MyTextView

创建一个工厂函数,它将在运行时知道根据设备iOS版本创建哪个子类。

如果我使用MyTextView作为参数,此解决方案可以正常工作。

MyTextView* textView = [Factory createWithFrame:frame];

当有一个继承自MyTextView (externalTextView:MyTextView)的类并使用特定方法扩展它时,问题就开始了, 它的initWithFrame方法将如下所示:

- (id)initWithFrame:(CGRect)frame {
    self = [Factory createWithFrame:frame];
    if (self) {
        ...
    }
    return self;
}

我没有打电话给超级initwithFrame,而是打电话给我的工厂。

当我调用externalTextView特定方法时,应用程序崩溃时出现错误, MyTextViewIos5 MyTextViewIos6 未实现调用的特定方法。

是否有解决方法使其正常工作?

2 个答案:

答案 0 :(得分:1)

只需为self = [Factory createWithFrame:]MyTextViewIos5而非自定义类的数据分配MyTextViewIos6。因此,您的自定义类的方法表等不存在,这就是它崩溃的原因。

继承的本质是,您必须子类MyTextViewIos5 MyTextViewIos6才能继承其功能。问题是你不知道哪个。

我建议将自定义类的功能分离为委托/协议设计。 MyTextView超类可以包含用于管理委托的代码。

类似的东西:

- (void)methodCustomSubclassWouldHaveOverridden
{ 
   [delegate handleThisForMe];
}

答案 1 :(得分:0)

如果您定义一个类,则从MyTextView派生的每个类都应在其自己的[super initWithFrame]方法中调用initWithFrame。如果您不需要对派生类实例进行任何自定义初始化,则可以完全省略init方法。

在一般情况下,您的工厂createWithFrame应该是:

- (MyTextView*)createWithFrame:(CGRect)frame {

    if (<iOS6>)
         return [[MyTextViewOS6 alloc] initWithFrame];
    if (<iOS5>)
         ...
}

现在,如果你的派生类不需要任何特殊的初始化,你可以简单地在每个类中保留initWIthFrame方法(并且只在基类中定义一个)。

或者,您可以在工厂中进行初始化,如下所示:

- (MyTextView*)createWithFrame:(CGRect)frame {

    if (<iOS6>)
         MyTextViewOS6* view = [[MyTextViewOS6 alloc] initWithFrame];
         view.iOS6SpecificProperty = ...;
         [view iOS6SpecificMethod:...];
         return view;
    if (<iOS5>)
         ...
}

你在做什么:

self = [Factory createWithFrame:frame];

正在分配MyTextView的新实例并替换self原始值。换句话说,当你这样做时:

externalTextView* view = [[externalTextView alloc] initWithFrame];

首先为externalTextView类型的对象分配内存;然后,调用该类的initWithFrame方法。现在,如果你在initWithFrame中执行:

self = [Factory createWithFrame:frame];

您正在通过工厂实例化一个新对象,并将指针指向self(最初指向通过alloc创建的对象)。

希望这有帮助。