Objective-C中的动态类型和返回值 [英] Dynamic typing and return values in Objective-C

查看:106
本文介绍了Objective-C中的动态类型和返回值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一种非常奇怪的行为,我无法理解.我有一个Texture类,其contentWidth属性的类型为int.此类包装在Image类中,该类具有类型为intwidth属性. Imagewidth可以简单地计算为基础纹理的contentWidth:

I have run into a very strange behaviour I can’t make sense of. I have a Texture class with contentWidth property of type int. This class is wrapped in a Image class that has a width property of type int. The width of an Image is computed simply as the contentWidth of the underlying texture:

- (int) width
{
    return texture.contentWidth;
}

现在Image由要读取图像大小的Button类(按组成而不是继承)使用:

Now the Image is used by a Button class (by composition, not inheritance) that wants to read the image size:

// image is of type ‘id’
int width = [image width];
int height = [image height];

问题在于,height变量设置得很好,而width变量包含NaN(–2147483648).我已经检查过尺寸了-它们大约是200×100左右,在int极限附近.同样,Xcode调试器工具提示正确显示了Texture中的两个属性,仅当宽度通过两个访问器后,数字才出现乱码.对象不会被释放.我想念什么?

The problem is that the height variable gets set just fine, whereas the width variable contains NaN (–2147483648). I have checked the dimensions – they are about 200×100 or so, nowhere near the int limit. Also the Xcode debugger tooltip shows both properties in the Texture correctly, only after the width gets through the two accessors the number gets garbled. The objects are not freed. What am I missing?

更新:我在Image类中扩展了访问器,以查看问题的根源:

Update: I have expanded the accessor in the Image class to see where the problem originates:

- (int) width
{
    const int w = texture.contentWidth;
    return w;
}

现在,当我在第一行中断时,w会正确设置.我跨过一步,执行返回到调用函数:

Now when I break on the first line, the w gets set correctly. I step over, the execution returns to the calling function:

- (void) foo
{
    int bar = [image width];
}

...现在bar包含NaN.

更新:嗯,知道了:

int foo = [image width]; // image is id, returns NaN
int bar = [(Image*) image width]; // correct value

image被声明为id,这就是这里的要点.有人可以解释一下吗?我有一种感觉,我没有调用正确的width方法,但是这里到底发生了什么?我总是尽可能严格地输入变量,但是id类型在这里很方便.我不知道它会导致这样的错误.

The image is declared as id, which is the point here. Could somebody explain this? I have got a feeling I am not calling the right width method, but what exactly is going on here? I always type my variables as strictly as possible, but here the id type is handy. I had no idea it could result in such a bug.

推荐答案

哦,很好.如果您对发生这种情况的原因感兴趣,请参阅《 Objective-C编程指南》第8章,

Oh well. If you are interested in why this situation happens, see the Objective-C Programming Guide, chapter 8, Return and Argument Types:

通常,方法不同 具有相同选择器的类 (同名)还必须共享 相同的返回值和参数类型.这 约束是由编译器强加的 允许动态绑定.因为 消息接收者的类别(和 因此,有关特定于课程的详细信息 要求执行的方法), 在编译时无法得知, 编译器必须使用 一样的名字.准备的时候 有关方法返回和 运行时系统的参数类型, 它仅创建一个方法描述 每个方法选择器.

In general, methods in different classes that have the same selector (the same name) must also share the same return and argument types. This constraint is imposed by the compiler to allow dynamic binding. Because the class of a message receiver (and therefore class-specific details about the method it’s asked to perform), can’t be known at compile time, the compiler must treat all methods with the same name alike. When it prepares information on method return and argument types for the runtime system, it creates just one method description for each method selector.

但是,当邮件发送到 静态类型的对象,类 接收者是编译器已知的. 编译器有权访问 有关类别的特定信息 方法.因此,该消息是 摆脱了对其的限制 返回和参数类型.

However, when a message is sent to a statically typed object, the class of the receiver is known by the compiler. The compiler has access to class-specific information about the methods. Therefore, the message is freed from the restrictions on its return and argument types.

这是GCC bugzilla中的错误报告(以及相应的博客文章 ).这种行为不是错误,但也不是很友好,因为编译器不会警告您(至少没有默认警告设置).

Here’s a bug report in the GCC bugzilla (and a corresponding blog post). The behaviour is not a bug, but it isn’t very friendly either, because the compiler does not warn you (at least not with the default warning settings).

这篇关于Objective-C中的动态类型和返回值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆