Objective-C中的动态类型和返回值
我遇到了一种我无法理解的非常奇怪的行为。我有一个Objective-C中的动态类型和返回值,objective-c,dynamic-typing,Objective C,Dynamic Typing,我遇到了一种我无法理解的非常奇怪的行为。我有一个Texture类,其contentWidth属性的类型为int。该类被包装在一个图像类中,该类具有类型为int的宽度属性。图像的宽度仅作为底层纹理的内容宽度计算: - (int) width { return texture.contentWidth; } 现在,图像由一个按钮类使用(通过合成,而不是继承),该类希望读取图像大小: // image is of type ‘id’ int width = [image width]; in
Texture
类,其contentWidth
属性的类型为int
。该类被包装在一个图像
类中,该类具有类型为int
的宽度
属性。图像的宽度
仅作为底层纹理的内容宽度
计算:
- (int) width
{
return texture.contentWidth;
}
现在,图像
由一个按钮
类使用(通过合成,而不是继承),该类希望读取图像大小:
// image is of type ‘id’
int width = [image width];
int height = [image height];
问题是height
变量设置得很好,而width
变量包含NaN
(-2147483648)。我已经检查了尺寸——它们大约是200×100左右,远未接近int
极限。另外,Xcode调试器工具提示正确显示纹理中的这两个属性,只有在宽度通过两个访问器后,数字才会出现混乱。对象不会被释放。我错过了什么
更新:我在Image
类中扩展了访问器,以查看问题的根源:
- (int) width
{
const int w = texture.contentWidth;
return w;
}
现在,当我在第一行中断时,w
设置正确。I跳过,执行返回到调用函数:
- (void) foo
{
int bar = [image width];
}
…现在,条
包含NaN
更新:嗯,明白了:
int foo = [image width]; // image is id, returns NaN
int bar = [(Image*) image width]; // correct value
图像
声明为id
,这就是此处的要点。有人能解释一下吗?我感觉我没有调用正确的width
方法,但这里到底发生了什么?我总是尽可能严格地键入变量,但这里的id
类型很方便。我不知道它会导致这样的错误。您的访问者不应该是:
- (int) width
{
return [texture contentWidth];
}
纹理是实例变量吗?如果是的话,您是否使用super在init方法或包装器类中对其进行了初始化?哦。如果您对这种情况发生的原因感兴趣,请参阅Objective-C编程指南第8章:
一般来说,不同的方法
具有相同选择器的类
(同名)也必须共享
返回和参数类型相同。这
约束是由编译器施加的
允许动态绑定。因为
消息接收器的类别(和
因此,关于
要求它执行的方法),
在编译时无法知道,则
编译器必须使用
名字一样。当它准备好的时候
有关方法返回和返回的信息
运行时系统的参数类型,
它只创建一个方法描述
对于每个方法选择器
但是,当消息发送到
静态类型对象,是
编译器知道接收器。
编译器可以访问
类的特定信息
方法。因此,信息是
摆脱了对它的限制
返回和参数类型
下面是GCC bugzilla中的一个(以及相应的一个)。该行为不是一个bug,但也不是很友好,因为编译器不会警告您(至少不会使用默认的警告设置)。您是否在纹理类中实现了contentWidth访问器?宽度和高度访问器之间的区别是什么?高度访问器是如何在图像中实现的?@Tim:没有区别,“高度”访问器看起来完全一样。当然,除了名称之外:)@Perspx:Yes,否则编译器会在Image类的“width”访问器中抱怨。两者是等效的-Objective-C将在编译期间将点访问器语法转换为传递的消息。从“良好实践”的角度来看,这是个好主意。。。在这种情况下,我会确保您的实例已正确初始化。我刚刚覆盖了纹理类上的“description”方法,并在那里记录了维度,它们都很好。