Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Ruby make #initialize private?

Tags:

private

ruby

I understand that Ruby's #initialize method is private. However, what stumps me is how Ruby makes the method private.

We normally define classes like this:

class Cat
  def initialize(name)
    @name = name
  end

  def say_name
    puts @name
  end
end

where #initialize seems to be defined publicly alongside #say_name. How does Ruby manage to make #initialize private after the class definition?

like image 555
conz Avatar asked Mar 31 '15 15:03

conz


People also ask

What is a real ruby made of?

A ruby is a pinkish red to blood-red colored gemstone, a variety of the mineral corundum (aluminium oxide). Ruby is one of the most popular traditional jewelry gems and is very durable. Other varieties of gem-quality corundum are called sapphires.

What makes a ruby a ruby?

Rubies are scientifically known as corundum, a rock-forming mineral and crystalline form of aluminium oxide which is two aluminium atoms and three oxygen atoms (Al2O3) in a close packed hexagonal structure. Corundum typically contains traces of iron, titanium, vanadium and/or chromium.

Are rubies man made?

Lab-created rubies are considered real because they are not much different from the natural ones. Rubies that are artificially produced are not the same as fake rubies, as they have different chemical structures from natural rubies.

How does a ruby become red?

Trace elements that become part of the mineral's crystal structure cause variations in its color. Chromium is the trace element that causes ruby's red, which ranges from an orangy red to a purplish red. The strength of ruby's red depends on how much chromium is present—the more chromium, the stronger the red color.


2 Answers

Yukihiro Matsumoto (the inventor of Ruby) has said:

#initialize is, by its design, supposed to be called only from within #new to separate per object/class initialization from the #new, thus you don't have to redefine #new. When you need/want to redefine #new, it's a sign of a bad design, I believe.

One of the reason #initialize being private is to tell you bad design.

So in summary it's a built in feature of Ruby that #initialize is automatically private and it's so developers won't easily call it outside of the .new class method.

like image 98
SteveTurczyn Avatar answered Oct 19 '22 05:10

SteveTurczyn


Very interesting question! I researched it and found some interesting things about Ruby, though I did not find the exact answer you're looking for.

initialize is a private instance method that is meant to be redefined on most objects. It comes from BasicObject, the Ruby class from which all objects and classes inherit.

Any new class you create in Ruby will have a private instance method called initialize:

class Q ; end
Q.private_instance_methods.include?(:initialize)
=> true

That instance method is inherited from BasicObject#initialize:

q = Q.new
q.method(:initialize)
=> #<Method: Q(BasicObject)#initialize>

And the method itself is not defined in Ruby, it comes from the C source of the language:

q.method(:initialize).source_location
=> nil

This is what that looks like in the Ruby source code (object.c file):

rb_define_private_method(rb_cBasicObject, "initialize", rb_obj_dummy, 0);

rb_obj_dummy is basically a no-op function. Which makes sense because the expectation is that you'll override initialize with your own implementation code in your class.

All that said, your original question was about why initialize doesn't become a public method when you define it in the public space in your class definition. I don't know. Normally if you do that for any other method it will become a public method:

class Q
  private
  def my_private_method() "private" end
end

Q.new.my_private_method
NoMethodError: private method `my_private_method' called for #<Q:0x007fc5ea39eab0>

class Q
  def my_private_method() "now i'm a public method" end
end

Q.new.my_private_method
=> "now i'm a public method"

So I guess somewhere else deep in the source code defining a method named "initialize" is handled differently from other methods. I couldn't find it, but maybe someone else can.

like image 27
devpuppy Avatar answered Oct 19 '22 07:10

devpuppy