实际上我来自 java 背景,我正在学习 objective-c 。我对 Objective-C 的奇怪行为感到非常困惑。“请阅读第 3 个问题,它很重要。”
问题是按顺序提供的,所以请按我和其他人都能理解的顺序给出答案。
问题一
我有两个派生自 NSObject
的类: A
和 B
:
@interface A : NSObject
@end
@interface B : NSobject
-(void)display; // It displays "I am class B"
@end
现在如果我这样做:
A *a = [[B alloc]init]; // Show warning not error (it must be illegal)
[a display]; // prints "I am class B"
它调用了类 B 的显示方法。我认为它不应该发生,因为:
A
没有方法display
.通过多态性。这可能是一种安全威胁,因为我正在创建任何类的引用并传递任何其他类的对象并通过它访问数据。
可能存在设计问题
Dog
类实例获取Printer
的对象上课,现在我调用print
Dog
上的方法实例。我引用了
NSArray
并传递了NSMutableArray
的对象现在我调用NSMutableArray
此实例上的方法。[nsarr addObject:@:abc];//看起来很奇怪
问题二
如果我有 Foo
协议(protocol),如果有任何类没有确认它。不应允许在协议(protocol)引用中获取该类的对象。
@protocol Foo
@required
-(void)abc;
@end
如果我调用:
id<Foo> obj= [[B alloc]init]; // Shows warning ignore it for now as it must be illegal also
[obj display]; // It will call display method which should be illegal
- 这不应该发生,因为
B
不符合协议(protocol)Foo
和obj
正在服用B
对象和调用B
实例方法。我认为它非常糟糕,因为多态性和安全性
问题三
如果我的类有一个类方法返回该类的一个未自动释放的对象,则编译器会显示警告。如果我将该类(不符合协议(protocol))方法返回的对象传递给协议(protocol)的引用。 (它应该是一个错误)。
id<Foo> obj = [Abc aClassMethodReturnsObjectWhichNotAutoreleased]; //show warning
它显示了一个很好的警告。 Abc
不符合协议(protocol)Foo
但是
id<Foo> obj = [NSArray arrayWithObjects:@"abc",@"def",nil]; // It does **not** show a warning as it will return autorelease object. NSArray doesn't conform protocol Foo
为什么上面的赋值给了NSArray
类不显示警告,因为它在前面的示例中显示。
提前致谢。
编辑
*回答第三个问题:*由于 NSArray 返回允许传入“id obj”的 id 对象,但在“aClassMethodReturnsObjectWhichNotAutoreleased”的情况下,该方法返回“ABC *”指针,这就是编译器的原因在这种情况下发出警告。
最佳答案
问题一:
A *a = [[B alloc]init]; //Show warning not error (it must be illegal)
[a display]; //prints "I am class B"
在这里,您为名为 a
的变量使用静态类型 A
。然后,您将另一种类型的对象 (B
) 分配给该变量。
与 java 不同,Objective-C 不会强制静态类型要求,但是它会在编译时警告您,因为编译器检测到声明的类型之间存在差异类型和对象的实际类型。不过,它很乐意将 B 对象填充到您的变量中,因此 a
现在指向您创建的 B
对象。一旦程序编译并运行(在运行时),A *a
将被视为与 id a
相同。
Objective-C 的另一个特性是您可以随时向任何对象发送任何消息。这是 Objective-C 动态特性的一部分。显然,在某些情况下,向对象发送错误消息会导致坏事 (tm) 发生,因此您需要确保只发送适当的消息。有多种函数可以在运行时测试对象的类,甚至可以在发送消息之前测试它是否能够处理特定消息,以防止坏事。如果您使用的是静态类型(如本例所示),那么编译器会发出警告,告诉您您可能犯了错误,应该检查代码。
问题 2:
这实际上与问题 1 非常相似。编译器警告您,您正在为变量分配看似不正确的值,但是在运行时您可以向任何对象发送任何消息,因此它会起作用在实际对象上,而不是类型声明中的“预期”对象。
问题 3:
好问题。我原以为你也会在那里收到警告。也许其他人可以提供帮助。我的第一个想法是这是一个错误,应该这样报告,但可能有一个我不知道的原因....
关于iphone - objective-c 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13322974/