在objective-C中,为什么我们不能alloc
+ init
或new
具有超类的基类对象,而我们可以使用超类的构造函数来初始化?
以下是一些代码:
s1
可以非常舒适地创建。
NSMutableString *s1=[NSString string];
NSLog(@"%@",s1);
但s2
和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分解为两个不同的语句时会发生什么?
答案 0 :(得分:4)
答案可以在Clang 3.3文档的Objective-C Features中找到:
相关结果类型
根据Cocoa惯例,具有某些名称的Objective-C方法 (“init”,“alloc”等)总是返回作为实例的对象 接收类的类型。据说这种方法具有“相关性” 结果类型“,意味着发送到这些方法之一的消息将 具有与接收器类的实例相同的静态类型。
因此在
NSMutableString *s2 = [[NSString alloc] init];
右侧的类型实际上是NSString *
而不是id
,并且将其分配给NSMutableString *
会产生“不兼容的指针类型”警告。
另一方面,
中的string
方法
NSMutableString *s1 = [NSString string];
没有“相关结果类型”,因此只返回id
,可以将其分配给NSMutableString *
。
仅当您使用id
作为中间类型时,将alloc / init分解为单独的语句才会禁止警告。使用NSString
或NSMutableString
,您仍会收到警告:
NSString *tmp4 = [NSString alloc];
NSMutableString *s4 = [tmp4 init]; // <-- Warning here
NSMutableString *tmp5 = [NSString alloc]; // <-- Warning here
NSMutableString *s5 = [tmp5 init];
根据文档,如果方法的返回类型与其类的类型兼容,并且如果:
,则该方法具有“相关结果类型”。答案 1 :(得分:0)
第一个案例
NSMutableString *s2=[[NSString alloc] init];
NSLog(@"%@",s2);
您要创建一个NSString
实例并在其上发送init
消息,最后您将NSString
实例分配给NSMutableString
。编译器知道您正在分配不兼容的指针类型。所以它警告你。
第二种情况
id mem=[NSString alloc];
NSMutableString *s3=[mem init];
您正在创建NSString
个实例并指定为类型id
。并在init
类型的对象上发送id
。 id 类型是通用的,编译器直到运行时才知道它的实际类型(动态类型)。所以它不会警告你。所以问题不在于嵌套调用。
最后我的观察结果只是:)。