开发者

question about overriding initialize method

开发者 https://www.devze.com 2022-12-13 00:38 出处:网络
I encountered a strange question about override initialize message of BigDecimal. class Test1 < String

I encountered a strange question about override initialize message of BigDecimal.

class Test1 < String
  def initialize(a, b)
    puts a
    puts b
  end
end

requ开发者_如何转开发ire 'bigdecimal'
class Test2 < BigDecimal
  def initialize(a, b)
    puts a
    puts b
  end
end

>> Test1.new('a', 'b')
a
b
>> Test2.new('a', 'b')
TypeError: wrong argument type String (expected Fixnum)
    from (irb):17:in `new'
    from (irb):17

Why I can override the initialize message of String, but not of BigDecimal?


When you look into sources of Ruby classes, you'll see that the String class defines method String#initialize, which is called after String#new (inherited from Object) for allocating a new instance. You don't call String#initialize (or #super) in your new instance so you got "" when you inspect the newly created object.

BigDecimal defines method Bigdecimal#new, which allocates its own object. Object creation consists of two parts - allocating space for new object and initializing it. You only defined initializing new object, so you stay with default allocating space for object. If you want to override it, you should define #new in your new class and call BigDecimal's #new with proper arguments.

Hope that clarifies a little what happen in your example.


Yes, BigDecimal implements the new class method and if you override that in your test2 class then you can write your Test2 initialize method in any way you want, for e.g.

class Test2 < BigDecimal
  def self.new(a)
    puts a
  end

  def initialize(a)
    puts a
  end
end

Test2.new("a")

The class method new is the object constructor which sets up the object state and allocates memory once the object is initialized by using the initialize method.

But generally we don't implement the new method as it is the default constructor method provided by ruby although it can be overridden by redefining it in your class if there is a strong reason for doing that and that is what BigDecimal has done.


It looks like there's some type checking occurring in BigDecimal.new(), which is getting upset before your overridden initialize is reached. See point 19 in this list

It's not often an issue (I remembered something but still had to look it up) but there's a new class method that, if I recall correctly, actually creates the object and then calls initialize.

Overriding new on the class, thus:

class Test2 < BigDecimal
  def Test2.new(a, b)
    puts a
    puts b
  end
end

Test2.new('42', 'banana')

gives the hoped-for answer.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号