2013-01-14 7 views
5

In Ruby, quando si effettua una nuova classe, definiremo il metodo di costruzione in questo modo:Perché definiamo `# initialize` invece di` new` ::

class Thing 
    def initialize 
    do_stuff 
    end 
end 

Tuttavia, quando in realtà facendo un esempio di l'oggetto, ci troviamo non chiamando initialize sull'istanza ma new sulla classe.

Stando così le cose, perché non definiamo invece ::new?

class Thing 
    def self.new 
    do_stuff 
    end 
end 

C'è qualcosa ::new fa beind le scene che initalize non definisce? Sono quei due completamente diversi? Definirebbe ::new funzionare? O è solo che def initialize è più corto (non) di def self.new?

Sto pensando che ci deve essere una buona ragione per la disparità.

+0

http: //blog.sidu.in/2007/12/rubys-new-as-factory.html –

risposta

10

Nuovo alloca lo spazio per il nuovo oggetto e lo crea. Quindi chiama il metodo di inizializzazione degli oggetti per creare un nuovo oggetto utilizzando la memoria allocata. Di solito, l'unica parte che si desidera personalizzare è la creazione effettiva e si accontenta di lasciare l'allocazione della memoria precedente al metodo Object.new, quindi si scrive un metodo di inizializzazione. Quali nuove sta facendo sotto il cofano sembra qualcosa di simile (se non in C):

class Object 
    def self.new(*args, &block) 
     object = allocate 
     object.send(:initialize, *args, &block) 
     return object 
    end 
end 

Così, quando si chiama Object.new, ciò che in realtà accade è:

1) La memoria viene assegnata 2) La viene chiamato il metodo di inizializzazione degli oggetti.

+0

http://www.ruby-forum.com/topic/61666 –

3
  • Elaborare il punto di Abrahamo, in effetti, sta invertendo la relazione di avvolgimento. Se avessi allocate come un primitivo e di solito definisci new, allora dovresti sempre fare cose comuni come chiamare allocate e restituire l'oggetto alla fine, che è una cosa ridondante da fare. Avendo new e initialize, il primo avvolgerà quest'ultimo, quindi è solo necessario definire ciò che è avvolto, non il wrapper.
  • new è un metodo di classe, quindi quando lo definisci, non hai accesso ai metodi di istanza e alle variabili di istanza per impostazione predefinita, e devi fare affidamento sugli accessor. D'altra parte, initialize è un metodo di istanza, quindi sarà più semplice lavorare con variabili di istanza e metodi di istanza.
5

Per fornire l'accesso alle variabili di istanza.

Le variabili di istanza, ad esempio @value, sono accessibili solo dalle istanze ma non da un metodo di classe. Questo differisce da linguaggi come Java in cui le variabili di istanza private hanno una classe piuttosto che un ambito di istanza e sono quindi accessibili dal costruttore statico.

class Thing 
    def initialize 
    @value = 42 
    end 
end 

class Thing 
    def self.new 
    # no way to set the value of @value !!!!!!!! 
    end 
end 

Per chi è interessato alla storia di Ruby, il modello a oggetti con variabili di istanza istanza-privato risale al Smalltalk. E troverai lo stesso modello nel moderno dialetto Smalltalk come Pharo, new è implementato in Object per chiamare self initialize in modo tale che le sottoclassi possano facilmente inizializzare le variabili di istanza.

+0

che non cambia il fatto che io odio dover usare la parola "inizializzare" dovrebbe essere chiamato post initialize o qualcosa del genere :) – rogerdpack

Problemi correlati