Ios 类实例化而不在所有构造函数中调用super
我有以下情况: 我正在扩展Ios 类实例化而不在所有构造函数中调用super,ios,inheritance,constructor,initialization,Ios,Inheritance,Constructor,Initialization,我有以下情况: 我正在扩展UITextView控件(MyTextView:UITextView)。根据运行时设备的版本,我有不同的实现。因此,目前我在MyTextView类的实现中有许多“if-else”语句 为了使其更易于维护,我想将其划分为不同的类: MyTextViewIos5:MyTextView,MyTextViewIos6:MyTextView 并创建一个工厂函数,该函数将在运行时根据设备iOS版本知道要创建的子类 如果我使用MyTextView作为参数,这个解决方案将非常有效 My
UITextView控件(MyTextView:UITextView)
。根据运行时设备的版本,我有不同的实现。因此,目前我在MyTextView
类的实现中有许多“if-else”语句
为了使其更易于维护,我想将其划分为不同的类:
MyTextViewIos5:MyTextView
,MyTextViewIos6:MyTextView
并创建一个工厂函数,该函数将在运行时根据设备iOS版本知道要创建的子类
如果我使用MyTextView作为参数,这个解决方案将非常有效
MyTextView* textView = [Factory createWithFrame:frame];
当有一个类继承自MyTextView(externalTextView:MyTextView)
并使用特定方法对其进行扩展时,问题就开始了,
其initWithFrame
方法如下所示:
- (id)initWithFrame:(CGRect)frame {
self = [Factory createWithFrame:frame];
if (self) {
...
}
return self;
}
- (MyTextView*)createWithFrame:(CGRect)frame {
if (<iOS6>)
MyTextViewOS6* view = [[MyTextViewOS6 alloc] initWithFrame];
view.iOS6SpecificProperty = ...;
[view iOS6SpecificMethod:...];
return view;
if (<iOS5>)
...
}
我没有调用superinitwithFrame
而是调用我的工厂
当我调用externalTextView
specific方法时,应用程序崩溃,错误是MyTextViewIos5或MyTextViewIos6未实现调用的特定方法
是否有一种解决方法使其工作?只需为
MyTextViewIos5
或MyTextViewIos6
分配self=[Factory createWithFrame:]
的inits数据,而不是自定义类。因此,自定义类的方法表等不存在,这就是它崩溃的原因
继承的本质是,为了继承它们的功能,您必须创建子类MyTextViewIos5
MyTextViewIos6
。问题是你不知道是哪个
我建议将自定义类的功能分离为委托/协议设计。MyTextView超类可以包含管理委托的代码
比如:
- (void)methodCustomSubclassWouldHaveOverridden
{
[delegate handleThisForMe];
}
- (MyTextView*)createWithFrame:(CGRect)frame {
if (<iOS6>)
return [[MyTextViewOS6 alloc] initWithFrame];
if (<iOS5>)
...
}
只需为
MyTextViewIos5
或MyTextViewIos6
而不是自定义类指定self=[Factory createWithFrame:
初始化数据。因此,自定义类的方法表等不存在,这就是它崩溃的原因
继承的本质是,为了继承它们的功能,您必须创建子类MyTextViewIos5
MyTextViewIos6
。问题是你不知道是哪个
我建议将自定义类的功能分离为委托/协议设计。MyTextView超类可以包含管理委托的代码
比如:
- (void)methodCustomSubclassWouldHaveOverridden
{
[delegate handleThisForMe];
}
- (MyTextView*)createWithFrame:(CGRect)frame {
if (<iOS6>)
return [[MyTextViewOS6 alloc] initWithFrame];
if (<iOS5>)
...
}
从
MyTextView
派生的每个类都应在其自己的initWithFrame
方法中调用[super initWithFrame]
,如果您定义了一个方法的话。如果不需要对派生类实例进行任何自定义初始化,则可以完全省略init方法
在一般情况下,您的工厂createWithFrame
应该类似于:
- (void)methodCustomSubclassWouldHaveOverridden
{
[delegate handleThisForMe];
}
- (MyTextView*)createWithFrame:(CGRect)frame {
if (<iOS6>)
return [[MyTextViewOS6 alloc] initWithFrame];
if (<iOS5>)
...
}
你在做什么:
self = [Factory createWithFrame:frame];
正在分配MyTextView
的新实例并替换self
原始值。换句话说,当您这样做时:
externalTextView* view = [[externalTextView alloc] initWithFrame];
首先,为类型为externalTextView
的对象分配内存;然后,调用该类的initWithFrame方法。现在,如果在initWithFrame中执行以下操作:
self = [Factory createWithFrame:frame];
您正在通过工厂实例化一个新对象,并将指向它的指针指定给self
(它最初指向通过alloc创建的对象)
希望这能有所帮助。如果您定义了一个类,那么从
MyTextView
派生的每个类都将在其自己的initWithFrame
方法中调用[super initWithFrame]
。如果不需要对派生类实例进行任何自定义初始化,则可以完全省略init方法
在一般情况下,您的工厂createWithFrame
应该类似于:
- (void)methodCustomSubclassWouldHaveOverridden
{
[delegate handleThisForMe];
}
- (MyTextView*)createWithFrame:(CGRect)frame {
if (<iOS6>)
return [[MyTextViewOS6 alloc] initWithFrame];
if (<iOS5>)
...
}
你在做什么:
self = [Factory createWithFrame:frame];
正在分配MyTextView
的新实例并替换self
原始值。换句话说,当您这样做时:
externalTextView* view = [[externalTextView alloc] initWithFrame];
首先,为类型为externalTextView
的对象分配内存;然后,调用该类的initWithFrame方法。现在,如果在initWithFrame中执行以下操作:
self = [Factory createWithFrame:frame];
您正在通过工厂实例化一个新对象,并将指向它的指针指定给self
(它最初指向通过alloc创建的对象)
希望这有帮助。为什么不想在init方法中调用
super
?我想了一会儿,您可以通过子类化alloc
来处理这个问题,但可能不行。(这是一种处理原始问题的“聪明”方法。)为什么不想在init方法中调用super
?我想了一会儿,您可以通过子类化alloc
来处理这个问题,但可能不行。(这是一种处理原始问题的“聪明”方法。)如果我知道自定义类功能将是什么,这是一个很好的解决方案。但是在我的例子中,我正在构建一个外部SDK,我不能对将要使用\inherit MyTextView类的自定义类做任何假设。@user2572953通过使用协议,您可以定义客户端需要实现的契约。对不起,我的错……我第一次没有正确理解您的解决方案。您是对的,将我的自定义功能放在委托中并在MyTextView类中处理它将起作用。这意味着我的自定义ios5和ios6类不会是MyTextView的子类,而只会实现由它定义的协议。这种方法可以工作,但远不如使用继承优雅。如果我没有其他选择,我会用它。谢谢!如果我知道什么是自定义类功能,这是一个很好的解决方案。但就我而言,我正在构建一个外部SDK,我可以