In Ruby, moduli e classi sono istanze delle classi Module
e Class
, rispettivamente. Derivano i loro nomi dalla costante a cui sono assegnati. Quando si scrive:
class A::B
# ...
end
si sta effettivamente scrivendo:
A::B ||= Class.new do
# ...
end
Qual è la sintassi assegnazione costante valida, e assume che la costante A
è stato inizializzato correttamente e che si riferisce a un Module
o Class
.
Ad esempio, si consideri come le classi sono solitamente definiti:
class A
# ...
end
Che cosa sta effettivamente accadendo è questo:
Object::A ||= Class.new do
# ...
end
Ora, quando si scrive:
class A
class B
# ...
end
end
Che in realtà sembra così:
(Object::A ||= Class.new).class_eval do
(A::B ||= Class.new).class_eval do
# ...
end
end
Ecco ciò che sta accadendo, in ordine:
- Un nuovo
Class
istanza è asssigned al A
costante di Object
, a meno che non è stato già inizializzato.
- Una nuova istanza
Class
è assegnata alla costante B
di A
, a meno che non sia già stata inizializzata.
Questo assicura l'esistenza di tutti classi esterne prima di tentare di definire eventuali classi interne.
C'è anche una modifica dell'ambito, che consente di accedere direttamente alle costanti di A
. Confronta:
class A
MESSAGE = "I'm here!"
end
# Scope of Object
class A::B
# Scope of B
puts MESSAGE # NameError: uninitialized constant A::B::MESSAGE
end
# Scope of Object
class A
# Scope of A
class B
# Scope of B
puts MESSAGE # I'm here!
end
end
Secondo this blog post, il core team di Ruby chiama la "classe corrente", il cref
. Sfortunatamente, l'autore non elabora, ma come nota, è separato dal contesto di self
.
As explained here, il cref
è un elenco collegata che rappresenta l'annidamento di moduli a un certo punto nel tempo.
La corrente cref
viene utilizzato per costante e variabile di classe ricerca e per def
, undef
e alias
.
Come gli altri hanno detto, sono diversi modi di esprimere la stessa cosa.
C'è, tuttavia, una sottile differenza. Quando si scrive class A::B
, si si assume che la classe A
è già stata definita. In caso contrario, riceverai uno NameError
e lo B
non sarà definito affatto.
scrivere moduli correttamente annidati:
class A
class B
end
end
Assicura la classe A
esiste prima di tentare di definire B
.
Ho aggiornato la domanda per dimostrare che questi due approcci non sono gli stessi. – nickh
@nickh, non è necessario modificare la domanda per includere le risposte. Dovresti [aggiornare le risposte che sono state utili e accettare quella che ha sicuramente risposto alla tua domanda] (http://stackoverflow.com/faq#howtoask). –
Il fatto è che nessuno di loro ha risposto alla domanda. Tutte le risposte dicono che i 2 approcci sono gli stessi, che non sono. – nickh