如何将'A类'转换为其子类'B类' - Objective-C

时间:2009-08-06 00:35:04

标签: objective-c inheritance casting subclassing

我正在使用一个框架来定义和使用'ClassA',它是NSObject的子类。我想添加一些变量和功能,所以我自然创建了'ClassB','ClassA'的子类

现在我的问题是这个。这个框架中的许多方法返回'ClassA'的实例,我想将它转换为我的子类。

例如采用这种方法:

- (ClassA *)doSomethingCool:(int)howCool

现在在我的代码中我试试这个:

ClassB * objB;
objB = (ClassB *)doSomethingCool(10); 

NSLog(@"objB className = %@", [objB className]);

运行得很好。没有编译或运行时错误或任何东西。但对我来说真正奇怪的是输出:

>> "objB className = ClassA"

铸造显然失败了。不知道此时发生了什么...... objB被输入为'ClassB',但它的className是'ClassA',它不会响应任何'ClassB'方法。

不确定这是怎么可能的......任何人都知道我在做错了什么?

我发现了一个类似的帖子,与我提出的here

完全相反

5 个答案:

答案 0 :(得分:26)

在Objective-C中转换对象变量通常是一个错误(有些情况下它是正确的,但从来没有这样的事情)。请注意,您没有投射对象 - 您正在向对象投射指针。然后,您有一个类型为ClassB*的指针,但它仍然指向ClassA的同一个实例。指出的事情根本没有改变。

如果您真的想将ClassA的实例转换为ClassB,则需要编写一个可以从ClassA创建ClassB实例的ClassB构造函数方法。如果您确实需要添加实例变量,这可能是您的最佳选择。

正如Jason所说,首先尝试一个类别通常是一个好主意。

答案 1 :(得分:19)

你不能只将超类强制转换为它的子类。它实际上并没有实现任何添加的变量/属性或方法。只要您尝试使用在子类上定义的方法对其进行消息传递,您将获得运行时异常,并且您的应用程序将要退出。你只能安全地向一个方向施展:从更具体到更一般。即,您可以使用ClassA的方法和属性安全地将ClassB转换为ClassA,但不能反过来。

可以这样想:你有一个Car(父类)和一个FourDoorSedan(子类)。每辆车都有一个发动机和两扇门。现在,假设你从某个地方买了一辆车,那就是你所知道的。你告诉接线员,这辆车是FourDoorSedan,但实际上事实证明并非如此。因此,当运营商做类似的事情时:openBackPassengerDoor,会发生什么?只有两扇门!这里也一样。

如果您只想向ClassA添加一些功能,请查看Objective-C类别,它们可能就是您想要的,并且不需要任何转换。但请仔细阅读文档,因为它们并非没有警告。

答案 2 :(得分:5)

如果您只想向现有对象添加方法,则子类化不是正确的方法。您可以使用名为category的语言功能将方法添加到现有类(及其实例)。

示例:

//"ClassA+doSomethingCool.h"
@interface ClassA (doSomethingCool)
- (ClassA *)doSomethingCool:(int)howCool;
@end


//"ClassA+doSomethingCool.m"
@implementation ClassA (doSomethingCool)
- (ClassA *)doSomethingCool:(int)howCool
{

}
@end

答案 3 :(得分:2)

Casting不会从一种类型的对象转换为另一种类型的对象。除非使用某种工厂模式,否则不能强制某些库更改对象类型并创建其他类型的对象。

答案 4 :(得分:0)

当您在返回的对象上调用其中一个子类方法时会发生什么?

ClassB * objB;
objB = (ClassB *)doSomethingCool(10);
[objB subClassMethod];

Obj-C非常自由而且输入类型,你甚至不需要事先知道类型,例如。您可以将所有ClassB引用更改为id。 我知道知道你有预期的类型更安全,但如果你的代码是正确的,那就不重要了。

相关问题