Domanda

Com'è possibile che Ruby consenta implicitamente metodi di accesso alla classe al di fuori della classe?

Esempio:

class Candy
    def land
        homer
    end
end

def homer
    puts "Hello"
end

Candy.new.land #Outputs Hello
È stato utile?

Soluzione

La definizione di " homer " Il metodo aggiunge il metodo alla classe Object. Non sta definendo una funzione gratuita.

La classe Candy eredita implicitamente da Object e quindi ha accesso ai metodi in Object. Quando chiami " homer " nella "terra" metodo, la risoluzione del metodo non riesce a trovare una definizione nella classe corrente, passa alla super classe, trova il metodo che hai aggiunto a Object e lo chiama.

Altri suggerimenti

Un modo semplice per scoprire cosa succede

  1. Quali classi / moduli vengono cercati per risolvere i metodi utilizzati negli oggetti Candy?

    p Candy.ancestors # = > [Candy, Object, Kernel]

  2. Candy ha un metodo chiamato homer?

    p Candy.instance_methods (false) .grep (" homer ") # = > []

    p Candy.private_instance_methods (false) .grep (" homer ") # = > []

  3. OK Candy non ha alcun metodo chiamato 'homer'.

  4. Le novità della catena di ricerca (vedi 1) = > & Quot; oggetto "

  5. L'oggetto ha un metodo chiamato " homer " ?    p Object.instance_methods (false) .grep (" homer ") # = > []

    p Object.private_instance_methods (false) .grep (" homer ") # = > [" homer "]

Candy ha Object nella sua catena di ricerca che a sua volta ha un metodo di istanza privato "homer" quindi la risoluzione del metodo ha successo

La dichiarazione def definisce sempre il metodo nella classe di qualunque sia al punto di definizione

  1. Che cos'è self prima della definizione di homer?

    p self # = > principale   def homer     mette " Ciao "   fine

  2. Quindi qual è il suo tipo?

    p self.class # = > Oggetto

Ecco perché homer finisce su Object

Tecnicamente, la definizione del metodo homer è in realtà sul modulo Kernel che è mescolato in Object , non su < code> Object direttamente. Quindi quando homer non è una variabile locale o un metodo di istanza definito su Candy , la catena di ereditarietà del metodo Ruby viene seguita attraverso Object e quindi per il modulo misto Kernel e quindi questo codice viene eseguito.

Modifica: Scusa, non so perché l'ho pensato. Sembra che il metodo viva davvero su Object . Non sono sicuro che faccia troppa differenza nella pratica, ma avrei dovuto confermare le cose prima di pubblicare.

Ruby non ha funzioni fluttuanti. Ogni metodo appartiene a qualche oggetto. I metodi che def al livello superiore stanno effettivamente diventando metodi di istanza della classe Object . Poiché tutto è un Object a un certo livello, tutti gli oggetti hanno accesso ai metodi di istanza di Object .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top