使用超类'实例初始化对象

时间:2011-05-17 10:55:08

标签: objective-c inheritance initialization copy superclass

假设有一个Superclass和一个此类superclassObject的实例 我创建了一个派生的ClassA

如何以这种方式实例化(初始化)派生类的对象classAObject,所有继承的字段都等于superclassObject的字段?

当然,我可以遍历所有字段并手动复制classAObject.property = [superclassObject.property copy]之类的值。但是这种方法的问题在于我可能不知道(或无法访问)超类的所有ivars /属性。 是否有更容易(也更通用)的方式?

似乎我错过了一些非常基本的东西......

我正在尝试这样做,因为我得到了一个已初始化的UIView(带框架,背景颜色,自动调整遮罩等),我想用我的自定义视图替换它,并使用相同的参数。

更新1

我找到this question,答案就是

  

通常不支持任何OO语言

然而

  

在Objective-C中,在某些情况下可能

好的,如果支持,我该怎么办?如果支持 ,我该如何实现?

更新2

我似乎找到了解决这个一般性问题的特殊情况的解决方案,明天我将测试并报告。

然而,这引出了另一个想法:如果我使用NSCoder对superclassObject进行编码(如果它当然实现<NSCoding>),然后使用编码器调用[[ClassA alloc] initWithCoder:coder]该怎么办?知道编码superclassObject的数据? 免责声明:嗯,我不熟悉编码概念(甚至根本不熟悉),所以最后一句可能是胡说八道。

3 个答案:

答案 0 :(得分:2)

如果我正确理解了这个问题,您就有了一个已建立的视图,您希望将其更改为其他类。大概是因为改变了它的功能。

克隆类和交换实例之间的类属性是在Java等语言中执行此类操作的唯一方法。

但是......在目标C中我们有类别。如果您要做的只是更改行为,那么解决方案可能是为UIView创建一个类别,以执行您需要的附加或覆盖功能。

第二个想法是研究为什么你不是首先创建正确的类,因此避免这个问题。

答案 1 :(得分:0)

使用ObjC运行时肯定是可能的,但它会有点毛茸茸......这是Apple的文档链接:Objective-C Runtime及其用法示例:Objective-C Runtime Programming

您将迭代所有属性,检查它们的属性以找出您可以设置的属性(即省略只读属性),在超类上获取它们的getter方法,读取值并使用子类上的setter方法进行设置。

在UIView的特定情况下,这可能有用 - 你会调整直到它工作。通常情况下可能很困难:那些没有作为属性暴露的ivars怎么办?你想复制它们吗?然后,您需要检查类中定义的属性以及该类实现的所有协议。而且我不确定是否有必要迭代你的超类的所有超类以获得所有定义的属性和ivars。

但是,仍有可能。

<强>更新

如果您要复制实例变量,那么可能您甚至可能没有触及属性而设置 - 我假设所有状态最终都保存在ivars中。所以在这种情况下也不需要触摸协议定义的属性。

但另一个可能运行良好的解决方案就是坚持公共接口(实际上是它的一部分:看似数据而不是功能):通过超类的属性读取数据并使用属性设置派生类,再次假设类将对数据做正确的事情。在这种情况下,协议属性同样重要,因为它们也是公共接口的一部分,它们的实现可以将状态保存到实例变量中。

同样,我不会尝试将此方法作为复制任何类的一般解决方案,但是如果复制一个特定类的数据可能会运行得很好并且您可以轻松彻底地测试您的案例。

答案 2 :(得分:0)

IFF 您的子类只向超类添加方法而任何存储(即ivars),然后您可以使用半黑魔法技术* ISA-混写”。 Rob Napier mentions it,以及解释所有内容的a blog post链接。

每个Objective-C实例在内存中都有一块存储空间用于其实例变量,但方法的实现都保存在另一个地方,在类对象的存储中。运行时使用实例的isa指针来获取类对象。

因此,如链接博客文章所示,可以将一个类的实例转换为另一个类,前提是它们具有完全相同的字段。正如Rob警告的那样,无法添加ivars,只能更改方法。

强制转换(MyDerivedClass *)instanceOfSuperclass仅在编译时有效。它所做的就是让编译器在比较类型时感到满意:它不会影响方法的运行时查找,因此instanceOfSuperclass仍然会像Superclass一样行动

编辑:最后的想法,因为我们已经在谈论危险的技术了,也许你可以创建一个帮助类来保存你想要添加到子类的ivars。 Whew ,现在我真的疯了!

我自己从未这样做过;我只报告一种可能对您有用的技术。 注意所讨论的所有警告。


*有趣地用于KVO