Cosa fa class << self
in Ruby ?
Cosa fa class << self
in Ruby ?
Risposte:
Innanzitutto, la class << foo
sintassi apre la foo
classe singleton (eigenclass). Ciò consente di specializzare il comportamento dei metodi chiamati su quell'oggetto specifico.
a = 'foo'
class << a
def inspect
'"bar"'
end
end
a.inspect # => "bar"
a = 'foo' # new object, new singleton class
a.inspect # => "foo"
Ora, per rispondere alla domanda: class << self
apre la self
classe singleton, in modo che i metodi possano essere ridefiniti per l' self
oggetto corrente (che all'interno di un corpo di classe o modulo è la classe o il modulo stesso ). Di solito, questo è usato per definire metodi di classe / modulo ("statici"):
class String
class << self
def value_of obj
obj.to_s
end
end
end
String.value_of 42 # => "42"
Questo può anche essere scritto come una scorciatoia:
class String
def self.value_of obj
obj.to_s
end
end
O ancora più breve:
def String.value_of obj
obj.to_s
end
Quando all'interno di una definizione di funzione, si self
riferisce all'oggetto con cui viene chiamata la funzione. In questo caso, class << self
apre la classe singleton per quell'oggetto; un uso è quello di implementare la macchina statale di un uomo povero:
class StateMachineExample
def process obj
process_hook obj
end
private
def process_state_1 obj
# ...
class << self
alias process_hook process_state_2
end
end
def process_state_2 obj
# ...
class << self
alias process_hook process_state_1
end
end
# Set up initial state
alias process_hook process_state_1
end
Quindi, nell'esempio sopra, ogni istanza di StateMachineExample
ha una process_hook
alias process_state_1
, ma nota come in quest'ultima, può ridefinire process_hook
( self
solo per , non influenzare altre StateMachineExample
istanze) a process_state_2
. Quindi, ogni volta che un chiamante chiama il process
metodo (che chiama ridefinibile process_hook
), il comportamento cambia a seconda dello stato in cui si trova.
class << self
, per creare metodi di classe / modulo. Espanderò probabilmente su quell'uso di class << self
, poiché è un uso molto più idiomatico.
a
's singleton_class
dal momento che a
' s classe (dopo la modifica inspect
) è una variante unica della String
classe. Se stesse cambiando la String
classe singleton , avrebbe effetto su tutte le altre String
istanze. Cosa c'è di più strano ancora è che se in seguito riapre String
a ridefinire inspect
poi a
sarà ancora raccogliere le nuove modifiche.
class << self
media qualcosa di più che il valore di self
è impostato uguale alla classe Singleton nel campo di applicazione del blocco?
Ho trovato una spiegazione semplice super-su class << self
, Eigenclass
e diversi tipi di metodi.
In Ruby, ci sono tre tipi di metodi che possono essere applicati a una classe:
I metodi di istanza e i metodi di classe sono quasi simili al loro omonimo in altri linguaggi di programmazione.
class Foo
def an_instance_method
puts "I am an instance method"
end
def self.a_class_method
puts "I am a class method"
end
end
foo = Foo.new
def foo.a_singleton_method
puts "I am a singletone method"
end
Un altro modo di accedere a un Eigenclass
(che include metodi singleton) è con la seguente sintassi ( class <<
):
foo = Foo.new
class << foo
def a_singleton_method
puts "I am a singleton method"
end
end
ora puoi definire un metodo singleton per il self
quale è la classe Foo
stessa in questo contesto:
class Foo
class << self
def a_singleton_and_class_method
puts "I am a singleton method for self and a class method for Foo"
end
end
end
foo.singleton_class.instance_methods(false)
per controllare.
Di solito, i metodi di istanza sono metodi globali. Ciò significa che sono disponibili in tutte le istanze della classe in cui sono state definite. Al contrario, un metodo singleton è implementato su un singolo oggetto.
Ruby memorizza i metodi nelle classi e tutti i metodi devono essere associati a una classe. L'oggetto su cui è definito un metodo singleton non è una classe (è un'istanza di una classe). Se solo le classi possono memorizzare metodi, come può un oggetto memorizzare un metodo singleton? Quando viene creato un metodo singleton, Ruby crea automaticamente una classe anonima per memorizzare quel metodo. Queste classi anonime sono chiamate metaclassi, note anche come classi singleton o occhiali da vista. Il metodo singleton è associato alla metaclasse che, a sua volta, è associata all'oggetto su cui è stato definito il metodo singleton.
Se più metodi singleton sono definiti all'interno di un singolo oggetto, vengono tutti memorizzati nella stessa metaclasse.
class Zen
end
z1 = Zen.new
z2 = Zen.new
class << z1
def say_hello
puts "Hello!"
end
end
z1.say_hello # Output: Hello!
z2.say_hello # Output: NoMethodError: undefined method `say_hello'…
Nell'esempio sopra, la classe << z1 modifica il sé corrente in modo che punti alla metaclasse dell'oggetto z1; quindi, definisce il metodo say_hello all'interno della metaclasse.
Le classi sono anche oggetti (istanze della classe integrata chiamata Class). I metodi di classe non sono altro che metodi singleton associati a un oggetto di classe.
class Zabuton
class << self
def stuff
puts "Stuffing zabuton…"
end
end
end
Tutti gli oggetti possono avere metaclassi. Ciò significa che le classi possono anche avere metaclassi. Nell'esempio sopra, la classe << self modifica sé in modo che punti alla metaclasse della classe Zabuton. Quando un metodo viene definito senza un ricevitore esplicito (la classe / oggetto su cui verrà definito il metodo), viene implicitamente definito nell'ambito corrente, ovvero il valore corrente di sé. Quindi, il metodo stuff è definito all'interno della metaclasse della classe Zabuton. L'esempio sopra è solo un altro modo per definire un metodo di classe. IMHO, è meglio usare la sintassi def self.my_new_clas_method per definire i metodi di classe, in quanto semplifica la comprensione del codice. L'esempio sopra è stato incluso, quindi capiamo cosa sta succedendo quando ci imbattiamo nella classe << auto-sintassi.
Ulteriori informazioni sono disponibili in questo post sulle lezioni di Ruby .
class Hi
self #=> Hi
class << self #same as 'class << Hi'
self #=> #<Class:Hi>
self == Hi.singleton_class #=> true
end
end
[fa self == thing.singleton_class
nel contesto del suo blocco] .
hi = String.new
def hi.a
end
hi.class.instance_methods.include? :a #=> false
hi.singleton_class.instance_methods.include? :a #=> true
hi
l'oggetto eredita il suo #methods
dal suo #singleton_class.instance_methods
e quindi dal suo #class.instance_methods
.
Qui abbiamo dato hi
il metodo dell'istanza di classe singleton:a
. Invece avrebbe potuto essere fatto con la classe << ciao .
hi
's #singleton_class
ha tutti i metodi di istanza hi
' s #class
ha, e forse alcuni più ( :a
qui).
[metodi di istanza di cosa #class
e #singleton_class
possono essere applicati direttamente alla cosa. quando ruby vede thing.a, cerca prima: una definizione del metodo in thing.singleton_class.instance_methods e poi in thing.class.instance_methods]
A proposito: chiamano la classe singleton dell'oggetto == metaclass == eigenclass .
Il metodo singleton è un metodo definito solo per un singolo oggetto.
Esempio:
class SomeClass
class << self
def test
end
end
end
test_obj = SomeClass.new
def test_obj.test_2
end
class << test_obj
def test_3
end
end
puts "Singleton's methods of SomeClass"
puts SomeClass.singleton_methods
puts '------------------------------------------'
puts "Singleton's methods of test_obj"
puts test_obj.singleton_methods
I metodi di Singleton di SomeClass
test
I metodi di Singleton di test_obj
test_2
test_3
In effetti, se scrivi estensioni C per i tuoi progetti Ruby, c'è davvero solo un modo per definire un metodo Module.
rb_define_singleton_method
So che questo business autonomo apre solo tutti i tipi di altre domande in modo da poter fare meglio cercando ogni parte.
Prima gli oggetti.
foo = Object.new
Posso fare un metodo per foo?
Sicuro
def foo.hello
'hello'
end
Cosa ci faccio?
foo.hello
==>"hello"
Solo un altro oggetto.
foo.methods
Ottieni tutti i metodi Object più il tuo nuovo.
def foo.self
self
end
foo.self
Solo l'oggetto Foo.
Prova a vedere cosa succede se fai foo da altri oggetti come Class e Module. Gli esempi di tutte le risposte sono belli da giocare, ma devi lavorare con idee o concetti diversi per capire davvero cosa sta succedendo con il modo in cui il codice è scritto. Quindi ora hai molti termini da consultare.
Singleton, Class, Module, self, Object ed Eigenclass sono stati cresciuti, ma Ruby non nomina così i Object Model. È più simile a Metaclass. Richard o __why ti mostra l'idea qui. http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html E se ti colpisce, prova a cercare Ruby Object Model nella ricerca. Due video che conosco su YouTube sono Dave Thomas e Peter Cooper. Provano anche a spiegare questo concetto. Dave ha impiegato molto tempo per ottenerlo, quindi non preoccuparti. Ci sto ancora lavorando. Perché altrimenti dovrei essere qui? Grazie per la tua domanda Dai un'occhiata anche alla libreria standard. Ha un modulo Singleton proprio come un FYI.
Questo è abbastanza buono. https://www.youtube.com/watch?v=i4uiyWA8eFk