2015-03-31 9 views
7

Ich verstehe, dass Rubys #initialize method is private. Was mich jedoch stümpft ist wie Ruby macht die Methode privat.Wie macht Ruby # initialisieren privat?

Wir definieren normalerweise Klassen wie folgt aus:

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

    def say_name 
    puts @name 
    end 
end 

wo #initialize scheint öffentlich neben #say_name definiert werden. Wie schafft es Ruby, #initialize nach der Klassendefinition privat zu machen?

+0

Sicherlich funktioniert OOP so? – AJFarmar

+0

Was gefragt wird, ist warum die 'initialize' Methode speziell ist. Es wurde nicht als privat deklariert. – tadman

+0

Yup, genau was Tadman gesagt hat! – conz

Antwort

9

Yukihiro Matsumoto (the inventor of Ruby) has said:

#initialize wird, durch sein Design, sollte nur von innen #new aufgerufen wird pro Objekt/Klasseninitialisierung vom #new zu trennen, so dass Sie müssen nicht neu definieren # Neu. Wenn Sie neu wollen/wollen, ist es ein Zeichen für ein schlechtes Design, glaube ich.

Einer der Gründe, warum #initialize privat ist, ist schlechtes Design zu sagen.

Also zusammenfassend ist es eine in Funktion von Ruby gebaut, dass #initialize automatisch privat ist und es ist so Entwickler wird es nicht leicht außerhalb der .new Klasse Methode aufrufen.

+1

Danke, aber ich habe mich gefragt, _how_ ist '# initialize' wurde privat gemacht, nachdem wir es definiert haben. Wenn wir die Klassendefinition beenden, passiert etwas im Hintergrund, das '# initialize' privatisiert, obwohl wir es öffentlich definiert haben? Oder ist es nur eine Magie, die in C land passiert? – conz

+0

Es ist Rubin. #initialize ist ein spezielles Schlüsselwort für Ruby und wenn es darauf stößt, stellt es sicher, dass es als privat betrachtet wird. – SteveTurczyn

3

Sehr interessante Frage! Ich habe es recherchiert und einige interessante Dinge über Ruby gefunden, obwohl ich nicht die genaue Antwort gefunden habe, nach der Sie suchen.

initialize ist eine private Instanzmethode, die für die meisten Objekte neu definiert werden soll. Es kommt von BasicObject, der Ruby-Klasse, von der alle Objekte und Klassen erben.

Jede neue Klasse, die Sie in Ruby schaffen eine private Instanzmethode initialize genannt haben:

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

Und die Methode selbst ist nicht definiert in:

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

Das Instanzmethode von BasicObject#initialize vererbt wird Ruby, es kommt von der C-Quelle der Sprache:

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

ist, was die looks like in dem Ruby-Quellcode (object.c-Datei):

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

rb_obj_dummy ist im Grunde ein no-op function. Das ergibt Sinn, weil Sie erwarten, dass Sie initialize mit Ihrem eigenen Implementierungscode in Ihrer Klasse überschreiben.

Alles, was gesagt wurde, war Ihre ursprüngliche Frage darüber, warum initialize nicht zu einer öffentlichen Methode wird, wenn Sie es im öffentlichen Raum in Ihrer Klassendefinition definieren. Ich weiß es nicht. Normalerweise, dass es für jede andere Methode, wenn Sie tun eine öffentliche Methode werden wird:

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" 

Also ich denke, irgendwo anders tief im Quellcode eine Methode namens „Initialize“ definiert, ist anders als andere Methoden behandelt. Ich konnte es nicht finden, aber vielleicht kann es jemand anderes.

Verwandte Themen