如何将“A 类”转换为其子类“B 类”-Objective-C
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1236434/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to cast 'Class A' to its subclass 'Class B' - Objective-C
提问by nrj
I'm using a framework which defines and uses 'ClassA', a subclass of NSObject. I would like to add some variables and functionality so naturally I created 'ClassB', a subclass of 'ClassA'
我正在使用一个框架来定义和使用'ClassA',NSObject 的一个子类。我想添加一些变量和功能,所以我很自然地创建了“ClassB”,它是“ClassA”的子类
Now my problem is this. Many of the methods within this framework return instances of 'ClassA' which I would like to cast to my subclass.
现在我的问题是这个。该框架中的许多方法都返回“ClassA”的实例,我想将其转换为我的子类。
For example take this method:
例如采取这种方法:
- (ClassA *)doSomethingCool:(int)howCool
Now in my code I try this:
现在在我的代码中我试试这个:
ClassB * objB;
objB = (ClassB *)doSomethingCool(10);
NSLog(@"objB className = %@", [objB className]);
This runs just fine. No compile or runtime errors or anything. But what is really odd to me is the output:
这运行得很好。没有编译或运行时错误或任何东西。但对我来说真正奇怪的是输出:
>> "objB className = ClassA"
The casting obviously failed. Not sure what's happened at this point... objB is typed as 'ClassB', but it's className is 'ClassA' and it won't respond to any 'ClassB' methods.
铸造显然失败了。不确定此时发生了什么...... objB 被输入为“ClassB”,但它的 className 是“ClassA”并且它不会响应任何“ClassB”方法。
Not sure how this is possible... Anyone know what I am doing wrong here?
不知道这怎么可能......有人知道我在这里做错了什么吗?
I found a similar post which is exact opposite of what I'm asking here
我发现了一个类似的帖子,这与我在这里问的完全相反
采纳答案by Chuck
Casting object variables in Objective-C is usually a mistake (there are a few cases where it's right, but never for this sort of thing). Notice that you aren't casting an object — you're casting a pointerto an object. You then have a pointer of type ClassB*, but it still points to the same instance of ClassA. The thing pointed to hasn't changed at all.
在 Objective-C 中转换对象变量通常是一个错误(在少数情况下它是正确的,但绝不是这种情况)。请注意,您不是在投射对象——而是在投射指向对象的指针。然后你有一个 type 的指针ClassB*,但它仍然指向 ClassA 的同一个实例。指向的东西根本没有改变。
If you really want to convert instances of ClassA to ClassB, you'll need to write a ClassB constructor method that can create a ClassB instance from a ClassA. If you really need to add instance variables, this might be your best choice.
如果您真的想将 ClassA 的实例转换为 ClassB,则需要编写一个 ClassB 构造函数方法,该方法可以从 ClassA 创建一个 ClassB 实例。如果您确实需要添加实例变量,这可能是您的最佳选择。
As Jason said, though, it's often a good idea to try a category first.
不过,正如杰森所说,先尝试一个类别通常是个好主意。
回答by Jason Coco
You can't just cast a super class to its subclass. It doesn't actually implement any of your added variables/properties or methods. As soon as you try to message it with a method you define on your subclass, you are going to get a runtime exception and your application is going to quit. You can only safely cast in one direction: from more specific to more general. I.e., you can cast our ClassB to a ClassA safely, using only the methods and properties of ClassA, but not the other way around.
您不能只是将超类转换为它的子类。它实际上并没有实现您添加的任何变量/属性或方法。一旦您尝试使用您在子类中定义的方法向它发送消息,您将收到运行时异常并且您的应用程序将退出。您只能安全地向一个方向投射:从更具体到更一般。即,您可以安全地将我们的 ClassB 转换为 ClassA,仅使用 ClassA 的方法和属性,而不是相反。
Think of it this way: you have a Car (the parent class) and a FourDoorSedan (the subclass). Every car has an engine and two doors. Now, let's say you are getting a car from somewhere, and that's really all you know about it. You tell the operator, that car is a FourDoorSedan, but in fact it turns out it's not. So when the operator does something like: openBackPassengerDoor, what happens? There are only two doors!! It's the same here.
可以这样想:您有一个 Car(父类)和一个 FourDoorSedan(子类)。每辆车都有一个引擎和两个门。现在,假设您从某个地方取车,这就是您所知道的全部内容。你告诉接线员,那辆车是四门轿车,但事实证明它不是。因此,当操作员执行以下操作时:openBackPassengerDoor,会发生什么?只有两扇门!!这里也是一样。
If you just want to add a little functionality to ClassA, check out Objective-C Categories, they're probably what you want and no casting will be required. Read the documentation carefully, however, because they are not without their caveats.
如果您只是想为 ClassA 添加一些功能,请查看 Objective-C Categories,它们可能就是您想要的,不需要强制转换。但是,请仔细阅读文档,因为它们并非没有警告。
回答by user151660
If you just want to add a method to existing objects, subclassing is not the correct way. You can add method to existing classes (and their instances) using a language feature called category.
如果您只想向现有对象添加方法,则子类化不是正确的方法。您可以使用称为category的语言功能向现有类(及其实例)添加方法。
Example:
例子:
//"ClassA+doSomethingCool.h"
@interface ClassA (doSomethingCool)
- (ClassA *)doSomethingCool:(int)howCool;
@end
//"ClassA+doSomethingCool.m"
@implementation ClassA (doSomethingCool)
- (ClassA *)doSomethingCool:(int)howCool
{
}
@end
回答by Dmitriy
Casting doesn't convert from one type of object to another. You can't force some library to change type of object and create another type of objects unless it utilizes some factory pattern.
转换不会从一种类型的对象转换为另一种类型。您不能强制某些库更改对象类型并创建另一种类型的对象,除非它使用某种工厂模式。
回答by Henry
What happens when you call one of your subclass methods on the returned object?
当您对返回的对象调用子类方法之一时会发生什么?
ClassB * objB;
objB = (ClassB *)doSomethingCool(10);
[objB subClassMethod];
Obj-C is pretty free and lose with types, you don't even need to know the type before hand, eg. you could change all of your ClassB references to id. I know it's safer to know you have the expected type but if your code is correct it shouldn't matter.
Obj-C 是非常自由的,并且没有类型,你甚至不需要事先知道类型,例如。您可以将所有 ClassB 引用更改为 id。我知道知道你有预期的类型会更安全,但如果你的代码是正确的,那就无关紧要了。

