Question about overriding the initialization method

I came across a strange question about redefining a BigDecimal message.

class Test1 < String def initialize(a, b) puts a puts b end end require '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 can I override String initialization message, but not BigDecimal?

+4
source share
3 answers

When you examine the sources of Ruby classes, you will see that the String class defines the String#initialize method, which is called after String#new (inherited from Object ) to select a new instance. You do not call String#initialize (or #super ) in your new instance to get a "" when validating a newly created object.

BigDecimal defines the Bigdecimal#new method, which allocates its own object. Creating an object consists of two parts: allocating space for a new object and initializing it. You just defined the initialization of the new object, so you will remain with the default assignment for the object. If you want to override it, you must define #new in your new class and call BigDecimal #new with the appropriate arguments.

Hope that clarifies a little what will happen in your example.

+2
source

Yes, BigDecimal implements a new class method, and if you override it in your test2 class, you can write your Test2 initialization method in any way, for example,

 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 constructor of the object, which sets the state of the object and allocates memory after the object is initialized using the initialize method.

But usually we don’t implement the new method, since it is the standard constructor method provided by ruby, although you can override it by overriding it in your class if there is a good reason for this, and this is what BigDecimal did.

+2
source

There seems to be some type checking in BigDecimal.new() that gets frustrated before you reach the overridden initialize . See Paragraph 19 on this list.

This is not often a problem (I remembered something, but I should have looked at it anyway), but there is a method of class new , which, if I remember correctly, actually creates an object, and then calls initialize .

Overriding new in the class, thus:

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

gives a reliable answer.

+1
source

All Articles