在obj-C中调用一个转换对象的方法

时间:2013-11-10 14:16:54

标签: ios objective-c casting

我有一种感觉,这将是一个非常快速的答案。我正在做关于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指针转换(铸造?)到船指针?如果是这样的话,为什么打电话失败?

3 个答案:

答案 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两者的意义不同。所以它不会起作用。