【问题标题】:child object initialised to parent子对象初始化为父对象
【发布时间】:2012-03-08 13:58:26
【问题描述】:

B 是 A 类的子类。

A * a = [[B alloc] init];
B * b = [[A alloc] init];

其中哪些是无效的,为什么?

当我输入这个时,我收到了第二件事的警告,但我不明白它的意思。它显示了“使用 'A *' 类型的表达式初始化 'B * __strong' 的不兼容指针类型”。也可能有人告诉我第二个表达式是否有效以及如何做。

【问题讨论】:

    标签: iphone objective-c ios casting


    【解决方案1】:

    如果BA子类,则它的实例可以在可以使用A 实例的任何地方使用。反之则不成立。

    这是一个使用 Apple 类的真实示例:考虑 NSArray 及其子类 NSMutableArray。因为NSMutableArray 是一个 NSArray,所以下面的赋值是有效的:

    NSArray *myArray = [[NSMutableArray alloc] init];
    

    但是,由于NSArray 不一定是NSMutableArray,所以下面的赋值是无效的:

    NSMutableArray *myArray = [[NSArray alloc] init];
    

    编辑 从语言的角度来看,这两个赋值都是有效的:代码将被编译,如果你避开 B 不被 @ 支持的方法,甚至可以运行987654333@,感谢Objective C的动态方法分派机制。但是编译器无法再验证涉及变量的代码,并告诉你其他潜在的问题。

    【讨论】:

    • 所以明确一点:第二个例子,在一个声明为 B 的地方使用 A 的实例,是无效的。
    • 那么哪一个是有效的?那么为什么会出现警告呢?
    • 所以第二个无效。这很清楚。但是一个正确的原因仍然不清楚。
    • @ShyamK 这是一个警告,而不是错误,因为分配一个不兼容的指针本身并不是错误的。它通常不正确的,但语言并没有禁止它,它甚至可以运行而不会造成任何麻烦。例如,如果我将NSArray 分配给NSMutableArray 指针,但只使用NSArrayNSMutableArray 都支持的方法,我的程序将正常运行。
    【解决方案2】:
    A * a = [[B alloc] init];  // OK
    B * b = [[A alloc] init];  // INCORRECT
    

    简单地说,第一行是有效的,因为 B 的任何实例都必然是 A 的实例。因此,可以将指向 B 实例的指针分配给 A* 类型的变量。

    由于类似的原因,第二行不正确:A 的实例不一定是 B 的实例,因此将指向 A 实例的指针分配给 B* 类型的变量是不合适的。更具体地说,在第二行中,您直接实例化 A,因此生成的对象绝对 不是 B 的实例。

    这样想:将任何正方形描述为矩形是正确的,但在没有额外信息的情况下说矩形是正方形是不正确的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-06-27
      • 2021-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多