Cosa fa class << selfin Ruby ?
Cosa fa class << selfin Ruby ?
Risposte:
Innanzitutto, la class << foosintassi apre la fooclasse 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 << selfapre la selfclasse singleton, in modo che i metodi possano essere ridefiniti per l' selfoggetto 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 selfriferisce all'oggetto con cui viene chiamata la funzione. In questo caso, class << selfapre 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 StateMachineExampleha una process_hookalias process_state_1, ma nota come in quest'ultima, può ridefinire process_hook( selfsolo per , non influenzare altre StateMachineExampleistanze) a process_state_2. Quindi, ogni volta che un chiamante chiama il processmetodo (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_classdal momento che a' s classe (dopo la modifica inspect) è una variante unica della Stringclasse. Se stesse cambiando la Stringclasse singleton , avrebbe effetto su tutte le altre Stringistanze. Cosa c'è di più strano ancora è che se in seguito riapre Stringa ridefinire inspectpoi asarà ancora raccogliere le nuove modifiche.
class << selfmedia 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, Eigenclasse 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 selfquale è la classe Foostessa 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
hil'oggetto eredita il suo #methodsdal suo #singleton_class.instance_methodse quindi dal suo #class.instance_methods.
Qui abbiamo dato hiil metodo dell'istanza di classe singleton:a . Invece avrebbe potuto essere fatto con la classe << ciao .
hi's #singleton_classha tutti i metodi di istanza hi' s #classha, e forse alcuni più ( :aqui).
[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