Reputation: 2929
so I have the following anonymous class definition:
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
But when I do:
fake_class.new 4
I just get undefined method 'new' for #<Class:0x00007fc065377c88>
I've tried doing
define_method :initialize do |value|
@value = value
end
no difference
the only way it responds to new is if I do
class << self
def new(value)
@value = value
end
end
but that obviously won' work as I need it to act like a real class.
Why do I see lots of tutorials using intialize
and it working as expected yet it doesn't seem to work for me? Is it becuase i'm defining it in rspec or somthing?
Upvotes: 2
Views: 1279
Reputation: 17873
Your code is correct but Integer
does not respond to .new
and so your child class will also not respond to .new
.
irb(main):001:0> Integer.new
NoMethodError (undefined method `new' for Integer:Class)
When you call Integer(123)
you actually call a global function defined here:
https://github.com/ruby/ruby/blob/v2_5_1/object.c#L3987
https://github.com/ruby/ruby/blob/v2_5_1/object.c#L3178
Upvotes: 2
Reputation: 28305
The issue here is nothing to do with rspec
, nor anonymous classes.
The problem is that in ruby, you cannot subclass Integer
*.
Ruby stores small Integer
s (formerly known as Fixnum
s) as immediate values, using some of the low bits of the word to tag it as such, instead of a pointer to an object on the heap. Because of that, you can't add methods to a single "instance" of Integer
, and you can't subclass it.
If you really want an "Integer-like" class, you could construct a workaround with a class that has an integer instance variable, and forward method calls appropriately:
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
* Technically you can, but since you cannot instantiate any objects from it, it's pretty useless :)
Upvotes: 4