You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RSpec中定义的匿名类无法响应new方法的问题咨询

问题根源:Ruby数值类的特殊实例机制

你遇到的问题核心在于你继承的是Ruby的Integer类,而它属于Ruby里特殊的不可变值类型,和普通Ruby类的实例创建逻辑完全不同。

为什么普通类只需要initialize就能实例化?

咱们平时看的教程里,大多是继承普通类(比如Object或者自定义类),这些类的new方法是Class类提供的默认实现——它会先调用allocate分配内存创建空实例,然后自动调用实例的initialize方法完成初始化。所以只需要定义initialize,就能通过new正常创建实例。

为什么继承Integer时initialize不生效?

Ruby的数值类(Integer、Float、String这些不可变值类型)的new方法是私有方法,而且Ruby本身并不推荐用new来创建它们的实例——你平时创建Integer实例都是用4、Integer(4)这种方式,而不是Integer.new(4)(不信你试试直接在irb里调用Integer.new(4),同样会报错private method 'new' called for Integer:Class)。

当你继承Integer后,你的匿名类也继承了这个私有new方法,所以你调用fake_class.new(4)时,本质是在调用一个私有方法,自然会报错。

为什么自己定义new能生效?

你显式在类的单例类里定义new方法,其实是覆盖了继承来的私有new方法,把它改成了公有的实例创建方法,所以能正常调用,但这确实不符合普通Ruby类的行为——因为普通类的new不需要自己定义,是由Class默认提供的。

解决方案:避开继承数值类,自己实现需要的功能

如果你的需求是创建一个类似Integer的自定义类,更合理的做法是不继承Integer,而是继承Object,然后实现你需要的方法:

let!(:fake_class) do
  Class.new(Object) do
    def initialize(value)
      @value = value.to_i # 确保是整数类型
    end

    def ==(other)
      @value == other
    end

    def coerce(other)
      [@value, other]
    end

    def to_s
      @value.to_s
    end

    # 如果需要支持数值运算,可以按需定义对应的方法
    def +(other)
      @value + other
    end

    def -(other)
      @value - other
    end
  end
end

这样调用fake_class.new(4)就会像教程里的普通类一样,自动调用initialize完成实例化,完全符合预期行为。

内容的提问来源于stack exchange,提问作者Thermatix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:21:21