我有一种感觉,这将是一个非常快速的答案。我正在做关于iOS开发的Paul Hegarty的斯坦福课程,他提到了铸造。我有一些Java的经验,但没有遇到过铸造,所以我想这可能是关于铸造的一般问题。我似乎无法在网上找到简洁的解释。他给出的代码是:
@interface Vehicle
- (void)move;
@end
@interface Ship : Vehicle
- (void)shoot;
@end
Ship *s = [[Ship alloc] init];
[s shoot];
[s move];
Vehicle *v = s;
[v shoot];
id obj = ...;
[obj shoot];
[obj someMethodNameThatNoObjectAnywhereRespondsTo];
// I understand up to this far, but it's the casting I'm having difficulty with
NSString *(hello) = @"hello";
[hello shoot];
Ship *helloShip = (Ship *)hello;
[helloShip shoot];
因此,在第一行中,他创建了一个名为hello的NSString指针。在第二行中,他调用了hello的shoot方法,这是一个NSString,并且该方法不存在,因此不起作用。 在第三行中,他正在创建一个指向名为helloShip的Ship对象的指针,并将其设置为等于什么? NSString指针转换(铸造?)到船指针?如果是这样的话,为什么打电话失败?
答案 0 :(得分:4)
Casting不会将对象转换为其他类。它只是让编译器将某个对象视为某种类型(Hermanns示例指出它)。
在您的示例中,hello
属于NSString *
类型。将其强制转换为Ship *
并调用其shoot
方法将编译 - 并崩溃。
即使在投放hello
之后仍然是NSString *
。
这并不意味着铸造是无用的。拿一个数组或例子。编译器不知道
除非您将结果转换为(正确)类型,否则[anArray objectAtIndex:x]
将返回什么。
另一个例子是:
-(void)objectTapped:(id)sender
{
if ([sender isKindOfClass:[UIButton class]])
{
UIButton *aButton = (UIButton *)sender;
//use all UIButton methods and properties
}
else if ([sender isKindOfClass:[UILabel class]])
{
UILabel *aLabel = (UILabel *)sender;
//use all UILabel methods and properties
}
}
因此,如果使用不当,铸造可能非常有用但也很危险。
答案 1 :(得分:4)
Casting实际上并不会更改对象的类,也不会重新格式化已转换对象中的任何内容。
Casing只告诉编译器“闭嘴!我是负责的程序员,我知道我在做什么。吃它并编译它让它运行。”
就是这样。不低于那个,不超过那个。通过这样做,您有责任确保对象能够很好地重新发送到发送的消息。
然而,使用ARC,您的样本甚至不会加入。您不能简单地将shoot
发送到Vehicle
类型的对象,因为Vehicle
类及其对象不响应shoot
。
如果没有ARC,您可以向每个对象发送任何消息,并希望对象在运行时响应它。
到目前为止,您的示例代码将运行,因为已分配(和已投放)到v
的对象仍为类型Ship
,它会响应shoot
。
NSString
永远不会回复shoot
,无论你将它投射到你想要的频率。 (当然,除非您将NSString
扩展为包含shoot
的类别。但这是一个不同的主题。)
答案 2 :(得分:0)
不,它不起作用,你正在尝试下面的东西
int age=(int)@"My age is 60";
这不起作用。
对于典型广播,它必须属于那种类型,在你的情况下,你试图将NSString *
转换为Ship
两者的意义不同。所以它不会起作用。