在 rspec 中定义的匿名 class 不会响应新的
Definied Anonymous class in rspec won't respond to new
所以我有以下匿名 class 定义:
let!(:fake_class) do
Class.new(Integer) do
def initialize(value)
@value = value
end
def ==(other)
@value == other
end
def coerce(other)
[@value, other]
end
def to_s
@value.to_s
end
end
end
但是当我这样做时:
fake_class.new 4
我刚刚得到undefined method 'new' for #<Class:0x00007fc065377c88>
我试过
define_method :initialize do |value|
@value = value
end
没有区别
它响应新消息的唯一方式是如果我这样做
class << self
def new(value)
@value = value
end
end
但这显然行不通,因为我需要它表现得像一个真正的 class。
为什么我看到很多使用 intialize
的教程并且它按预期工作但它似乎不适合我?是因为我在 rspec 之类的地方定义它吗?
您的代码是正确的,但是 Integer
没有响应 .new
因此您的 child class 也不会响应 .new
。
irb(main):001:0> Integer.new
NoMethodError (undefined method `new' for Integer:Class)
当您调用 Integer(123)
时,您实际上调用了此处定义的全局函数:
https://github.com/ruby/ruby/blob/v2_5_1/object.c#L3987
https://github.com/ruby/ruby/blob/v2_5_1/object.c#L3178
此处的问题与rspec
无关,也与匿名class无关。
问题是在ruby,你不能subclass Integer
*.
Ruby 将小的 Integer
s(以前称为 Fixnum
s)存储为立即值,使用单词的一些低位来标记它,而不是指向堆上对象的指针。因此,您不能将方法添加到 Integer
的单个 "instance",也不能将其子 class。
如果您真的想要 "Integer-like" class,您可以使用具有整数实例变量的 class 构建变通方法,并适当地转发方法调用:
class FakeInteger
def initialize(integer)
@integer = integer
end
def method_missing(name, *args, &blk)
ret = @integer.send(name, *args, &blk)
ret.is_a?(Numeric) ? FakeInteger.new(ret) : ret
end
end
* 技术上你可以,但是因为你不能从它实例化任何对象,所以它很没用:)
所以我有以下匿名 class 定义:
let!(:fake_class) do
Class.new(Integer) do
def initialize(value)
@value = value
end
def ==(other)
@value == other
end
def coerce(other)
[@value, other]
end
def to_s
@value.to_s
end
end
end
但是当我这样做时:
fake_class.new 4
我刚刚得到undefined method 'new' for #<Class:0x00007fc065377c88>
我试过
define_method :initialize do |value|
@value = value
end
没有区别
它响应新消息的唯一方式是如果我这样做
class << self
def new(value)
@value = value
end
end
但这显然行不通,因为我需要它表现得像一个真正的 class。
为什么我看到很多使用 intialize
的教程并且它按预期工作但它似乎不适合我?是因为我在 rspec 之类的地方定义它吗?
您的代码是正确的,但是 Integer
没有响应 .new
因此您的 child class 也不会响应 .new
。
irb(main):001:0> Integer.new
NoMethodError (undefined method `new' for Integer:Class)
当您调用 Integer(123)
时,您实际上调用了此处定义的全局函数:
https://github.com/ruby/ruby/blob/v2_5_1/object.c#L3987
https://github.com/ruby/ruby/blob/v2_5_1/object.c#L3178
此处的问题与rspec
无关,也与匿名class无关。
问题是在ruby,你不能subclass Integer
*.
Ruby 将小的 Integer
s(以前称为 Fixnum
s)存储为立即值,使用单词的一些低位来标记它,而不是指向堆上对象的指针。因此,您不能将方法添加到 Integer
的单个 "instance",也不能将其子 class。
如果您真的想要 "Integer-like" class,您可以使用具有整数实例变量的 class 构建变通方法,并适当地转发方法调用:
class FakeInteger
def initialize(integer)
@integer = integer
end
def method_missing(name, *args, &blk)
ret = @integer.send(name, *args, &blk)
ret.is_a?(Numeric) ? FakeInteger.new(ret) : ret
end
end
* 技术上你可以,但是因为你不能从它实例化任何对象,所以它很没用:)