【问题标题】:Dynamic typing and return values in Objective-CObjective-C 中的动态类型和返回值
【发布时间】:2009-07-11 08:44:24
【问题描述】:

我遇到了一个非常奇怪的行为,我无法理解。我有一个Texture 类,其contentWidth 属性类型为int。此类包装在具有width 类型intwidth 属性的Image 类中。 Imagewidth 被简单地计算为底层纹理的 contentWidth

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

现在Image 被想要读取图像大小的Button 类(通过组合,而不是继承)使用:

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

问题在于height 变量设置得很好,而width 变量包含NaN (–2147483648)。我检查了尺寸——它们大约是 200×100 左右,远不及int 的限制。此外,Xcode 调试器工具提示正确显示了Texture 中的两个属性,只有在宽度通过两个访问器之后,数字才会出现乱码。对象没有被释放。我错过了什么?


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

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

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

- (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 类型很方便。我不知道它会导致这样的错误。

【问题讨论】:

  • 您是否在 Texture 类中实现了 contentWidth 访问器?
  • 宽度和高度访问器有什么区别? Image中的高度访问器是如何实现的?
  • @Tim:没有区别,'height' 访问器看起来完全一样。当然,除了名字:)
  • @Perspx:是的,否则编译器会在 Image 类的“width”访问器中报错。

标签: objective-c dynamic-typing


【解决方案1】:

哦,好吧。如果您对为什么会发生这种情况感兴趣,请参阅 Objective-C 编程指南,第 8 章,Return and Argument Types

一般来说,不同的方法 具有相同选择器的类 (同名)也必须共享 相同的返回和参数类型。这 约束是由编译器强加的 允许动态绑定。因为 消息接收者的类(和 因此特定于类的详细信息 它被要求执行的方法), 在编译时无法知道, 编译器必须处理所有方法 同名。当它准备 有关方法返回的信息和 运行时系统的参数类型, 它只创建一种方法描述 每个方法选择器。

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

这是 GCC bugzilla 中的 bug report(以及相应的 blog post)。该行为不是错误,但也不是很友好,因为编译器不会警告您(至少在默认警告设置下不会)。

【讨论】:

    【解决方案2】:

    你的访问者不应该是:

    - (int) width
    {
        return [texture contentWidth];
    }
    

    纹理是实例变量吗?如果是,您是否在 init 方法或您的包装类中进行了 super 初始化?

    【讨论】:

    • 两者是等价的——Objective-C会在编译期间将点访问器语法转换为传递的消息。
    • 从“良好实践”的角度来看,无论如何这都是个好主意...在这种情况下,我会确保您的实例已正确初始化。
    • 我刚刚覆盖了 Texture 类的“description”方法并在那里记录了尺寸,它们很好。
    猜你喜欢
    • 1970-01-01
    • 2020-11-15
    • 2022-12-03
    • 2015-12-19
    • 2018-12-08
    • 2014-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多