使用“BaseClass *”类型的表达式初始化“SubClass *__strong”时不兼容的指针类型

2024-02-16

在 Objective-C 中,为什么我们不能alloc+init or new一个带有超类的基类对象,而我们可以使用超类的构造函数来初始化?

下面是一些代码:

s1可以很轻松地创建。

NSMutableString *s1=[NSString string];
NSLog(@"%@",s1);

But s2 and s3不能,并发出警告

Incompatible pointer types initializing 'SubClass *__strong' with an expression of type'BaseClass *'

NSMutableString *s2=[[NSString alloc] init];
NSLog(@"%@",s2);

NSMutableString *s3=[NSString new];
NSLog(@"%@",s3);

//here no warning.
id mem=[NSString alloc];
NSMutableString *s4=[mem init];
NSLog(@"%@",s4);

当我们将 alloc + init 分解为两个不同的语句时会发生什么?


答案可以在Objective-C 特性 http://clang.llvm.org/docs/LanguageExtensions.html#objective-c-featuresClang 3.3 文档的内容:

相关结果类型

根据 Cocoa 约定,具有特定名称的 Objective-C 方法 (“init”、“alloc”等)始终返回作为以下对象实例的对象 接收类的类型。据说此类方法具有“相关 结果类型”,这意味着发送到这些方法之一的消息将 与接收器类的实例具有相同的静态类型。

因此在

NSMutableString *s2 = [[NSString alloc] init];

右侧的类型实际上是NSString *并不是id,并将其分配给NSMutableString *给出“不兼容的指针类型”警告。

另一方面,string中的方法

NSMutableString *s1 = [NSString string];

没有“相关结果类型”,所以它只返回一个id可以分配给NSMutableString *.

仅当您使用时,将 alloc/init 分成单独的语句才会抑制警告id作为中间类型。和NSString or NSMutableString您仍然收到警告:

NSString *tmp4 = [NSString alloc];
NSMutableString *s4 = [tmp4 init]; // <-- Warning here

NSMutableString *tmp5 = [NSString alloc]; // <-- Warning here
NSMutableString *s5 = [tmp5 init];

根据文档,如果方法的返回类型与其类的类型兼容并且满足以下条件,则该方法具有“相关结果类型”:

  • 第一个单词是“alloc”或“new”,并且该方法是类方法,或者
  • 第一个单词是“autorelease”、“init”、“retain”或“self”,该方法是实例方法。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用“BaseClass *”类型的表达式初始化“SubClass *__strong”时不兼容的指针类型 的相关文章

随机推荐