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

nrj*_*nrj 26 inheritance casting objective-c subclassing

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

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

例如,采用这种方法:

- (ClassA *)doSomethingCool:(int)howCool
Run Code Online (Sandbox Code Playgroud)

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

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

NSLog(@"objB className = %@", [objB className]);
Run Code Online (Sandbox Code Playgroud)

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

>> "objB className = ClassA"
Run Code Online (Sandbox Code Playgroud)

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

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

我发现了一个类似的帖子,与我在这里提出的要求完全相反

Chu*_*uck 26

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

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

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


Jas*_*oco 19

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

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

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

  • 如果`doSomethingCool:`yes _did_返回类型为'ClassB`的对象,你可以进行转换.它的返回类型是`ClassA`,但它实际上可以返回`ClassB`的对象(因为`ClassB`"是一个"ClassA`).如果你_know_`doSomethingCool:`返回一个类型为'ClassB`的对象(你可以检查使用`[objB isKindOfClass:[ClassB class]]`如果你不确定的话),那么可以安全地投射和发送一条消息to`objB`告诉它执行`ClassB`方法.您也可以使用`respondsToSelector`来确定_really_. (4认同)

use*_*660 5

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

例:

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


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

}
@end
Run Code Online (Sandbox Code Playgroud)