17

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

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

当然,我可以循环浏览所有字段并手动复制classAObject.property = [superclassObject.property copy]. 但是这种方法的问题是我可能不知道(或无法访问)超类的所有 ivars/属性。有没有更简单(更通用)的方法?

看来我错过了一些非常基本的东西......

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

更新 1

我找到了这个问题,那里的答案说

通常不支持任何 OO 语言

然而

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

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

更新 2

看来我已经找到了解决这个一般问题的特殊情况的方法,明天我将对其进行测试并报告。

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

4

3 回答 3

2

如果我正确理解了这个问题,那么您有一个既定的观点,您想将其更改为不同的班级。大概是为了改变它的功能。

在类之间克隆类属性和交换实例是在 Java 等语言中做这种事情的唯一方法。

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

第二个想法是首先研究为什么你没有创建正确的类,从而避免整个问题。

于 2011-05-17T23:43:22.907 回答
0

如果您的子类只向超类添加方法而不是任何存储(即 ivars),那么您可以使用一种称为“isa-swizzling”的半黑魔法技术* Rob Napier提到了它,并链接到解释这一切的博客文章。

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

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

强制转换(MyDerivedClass *)instanceOfSuperclass仅在编译时有效。它所做的只是让编译器在比较类型时感到高兴:它不会影响方法的运行时查找,所以你instanceOfSuperclass仍然Superclass.

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

我自己从来没有这样做过;我只报告一种可能对您有用的技术。注意您在讨论此问题时看到的所有警告。


*有趣的是,用于KVO

于 2011-05-17T23:45:24.343 回答
0

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

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

在 UIView 的特定情况下,这可能会起作用 - 您将调整直到它起作用。一般来说,这可能很困难:不作为属性公开的 ivars 呢?你想全部复制吗?然后你需要检查类中定义的属性和类实现的所有协议。而且我不确定是否不需要遍历超类的所有超类来获取所有定义的属性和 ivars。

但是,仍然是可能的。

更新

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

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

同样,我不会尝试将这种方法作为复制任何类的通用解决方案,但在复制一个可能运行良好的特定类的数据的情况下,您可以轻松彻底地测试您的案例。

于 2011-05-17T14:49:13.487 回答