2015-03-31 11 views
7

Capisco che Ruby's #initialize method is private. Tuttavia, ciò che mi ostacola è in che modo Ruby rende privato il metodo.In che modo Ruby rende #initialize privato?

Normalmente definire le classi in questo modo:

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

    def say_name 
    puts @name 
    end 
end 

dove #initialize sembra essere definito pubblicamente a fianco #say_name. Come fa Ruby a rendere privato #initialize dopo la definizione della classe?

+0

Sicuramente è così che funziona OOP? – AJFarmar

+0

Ciò che viene chiesto è perché il metodo 'initialize' è speciale. Non è stato dichiarato come privato. – tadman

+0

Sì, esattamente quello che ha detto Tadman! – conz

risposta

9

Yukihiro Matsumoto (the inventor of Ruby) has said:

#initialize è, per il suo design, dovrebbe essere chiamato solo dall'interno #new di separare per oggetto l'inizializzazione/classe dal #new, quindi non si ha a ridefinire # nuovo. Quando hai bisogno/vuoi ridefinire #new, credo che sia un segno di un cattivo design.

Uno dei motivi per cui #initialize è privato è quello di dirti una cattiva progettazione.

Quindi, in sintesi si tratta di un costruito in funzione di Ruby che #initialize è automaticamente privata ed è così gli sviluppatori non sarà facile chiamare al di fuori del metodo .new di classe.

+1

Grazie, ma mi stavo chiedendo _how_ è '# initialize' reso privato dopo averlo definito. Quando finiamo la definizione della classe, c'è qualcosa che accade in background che privatizza '# initialize', anche se l'abbiamo definita pubblicamente? O è solo un po 'di magia che accade in C? – conz

+0

È Ruby. #initialize è una parola chiave speciale per Ruby e quando la incontra, si assicura che sia considerata privata. – SteveTurczyn

3

Domanda molto interessante! Ho fatto delle ricerche e ho trovato alcune cose interessanti su Ruby, anche se non ho trovato la risposta esatta che stai cercando.

initialize è un metodo di istanza privato che deve essere ridefinito sulla maggior parte degli oggetti. Viene da BasicObject, la classe Ruby da cui ereditano tutti gli oggetti e le classi.

Qualsiasi nuova classe si crea in Ruby avrà un metodo di istanza privato chiamato initialize:

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

Questo metodo di istanza viene ereditato dalla BasicObject#initialize:

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

E il metodo in sé non è definito in Ruby, proviene dalla sorgente C della lingua:

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

Questo è ciò che looks like nel codice sorgente di Ruby (object.c file):

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

rb_obj_dummy è fondamentalmente un no-op function. Il che ha senso perché l'aspettativa è che tu sostituirai initialize con il tuo codice di implementazione nella tua classe.

Detto questo, la tua domanda iniziale riguardava il motivo per cui l'inizializzazione non diventa un metodo pubblico quando lo definisci nello spazio pubblico nella definizione della classe. Non lo so. Normalmente, se lo si fa per qualsiasi altro metodo che diventerà un metodo pubblico:

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" 

Quindi credo che da qualche altra parte in profondità nel codice sorgente che definisce un metodo denominato "Initialize" viene gestita in modo diverso da altri metodi. Non riuscivo a trovarlo, ma forse qualcun altro può.

Problemi correlati