O que class << self
faz em Ruby ?
O que class << self
faz em Ruby ?
Respostas:
Primeiro, a class << foo
sintaxe abre a foo
classe singleton (classe própria). Isso permite que você especialize o comportamento dos métodos chamados nesse objeto específico.
a = 'foo'
class << a
def inspect
'"bar"'
end
end
a.inspect # => "bar"
a = 'foo' # new object, new singleton class
a.inspect # => "foo"
Agora, para responder à pergunta: class << self
abre self
's única classe, de modo que os métodos podem ser redefinidos para o atual self
objeto (que dentro de um corpo de classe ou módulo é a classe ou módulo em si ). Normalmente, isso é usado para definir métodos de classe / módulo ("estático"):
class String
class << self
def value_of obj
obj.to_s
end
end
end
String.value_of 42 # => "42"
Isso também pode ser escrito como uma abreviação:
class String
def self.value_of obj
obj.to_s
end
end
Ou ainda mais curto:
def String.value_of obj
obj.to_s
end
Quando dentro de uma definição de função, self
refere-se ao objeto com o qual a função está sendo chamada. Nesse caso, class << self
abre a classe singleton para esse objeto; um uso disso é implementar a máquina de estado de um homem pobre:
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
Portanto, no exemplo acima, cada instância de StateMachineExample
tem um process_hook
alias process_state_1
, mas observe como, no último, ele pode redefinir process_hook
( self
apenas por não afetar outras StateMachineExample
instâncias) para process_state_2
. Portanto, cada vez que um chamador chama o process
método (que chama de redefinível process_hook
), o comportamento muda dependendo do estado em que ele está.
class << self
, para criar métodos de classe / módulo. Provavelmente vou expandir esse uso de class << self
, pois esse é um uso muito mais idiomático.
a
é singleton_class
desde a
's classe (após a mudança inspect
) é uma variante única da String
classe. Se estivesse mudando a String
classe singleton , isso afetaria todas as outras String
instâncias. O mais estranho ainda é que se você reabrir mais tardeString
para redefinir inspect
, a
ainda assim receberá as novas alterações.
class << self
nada média mais do que o valor self
é definido igual à classe singleton dentro do escopo do bloco?
Encontrei uma explicação super simples sobre class << self
,Eigenclass
e vários tipos de métodos.
No Ruby, existem três tipos de métodos que podem ser aplicados a uma classe:
Os métodos de instância e métodos de classe são quase semelhantes aos homônimos em outras linguagens de programação.
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
Outra maneira de acessar um Eigenclass
(que inclui métodos singleton) é com a seguinte sintaxe ( class <<
):
foo = Foo.new
class << foo
def a_singleton_method
puts "I am a singleton method"
end
end
agora você pode definir um método singleton para o self
qual é a Foo
própria classe neste contexto:
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)
para verificar.
Geralmente, métodos de instância são métodos globais. Isso significa que eles estão disponíveis em todas as instâncias da classe em que foram definidas. Por outro lado, um método singleton é implementado em um único objeto.
Ruby armazena métodos em classes e todos os métodos devem ser associados a uma classe. O objeto no qual um método singleton é definido não é uma classe (é uma instância de uma classe). Se apenas classes podem armazenar métodos, como um objeto pode armazenar um método singleton? Quando um método singleton é criado, Ruby cria automaticamente uma classe anônima para armazenar esse método. Essas classes anônimas são chamadas de metaclasses, também conhecidas como classes singleton ou autoclasses. O método singleton está associado à metaclasse que, por sua vez, está associada ao objeto no qual o método singleton foi definido.
Se vários métodos singleton forem definidos em um único objeto, todos serão armazenados na mesma 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'…
No exemplo acima, a classe << z1 altera o self atual para apontar para a metaclasse do objeto z1; em seguida, define o método say_hello na metaclasse.
Classes também são objetos (instâncias da classe interna chamada Class). Os métodos de classe nada mais são do que métodos singleton associados a um objeto de classe.
class Zabuton
class << self
def stuff
puts "Stuffing zabuton…"
end
end
end
Todos os objetos podem ter metaclasses. Isso significa que as classes também podem ter metaclasses. No exemplo acima, a classe << self modifica a si mesma, de modo que aponta para a metaclasse da classe Zabuton. Quando um método é definido sem um receptor explícito (a classe / objeto no qual o método será definido), ele é definido implicitamente no escopo atual, ou seja, o valor atual de self. Portanto, o método stuff é definido dentro da metaclasse da classe Zabuton. O exemplo acima é apenas outra maneira de definir um método de classe. IMHO, é melhor usar a sintaxe def self.my_new_clas_method para definir métodos de classe, pois isso facilita a compreensão do código. O exemplo acima foi incluído para que possamos entender o que está acontecendo quando encontramos a auto-sintaxe da classe <<.
Informações adicionais podem ser encontradas neste post sobre Ruby Classes .
class Hi
self #=> Hi
class << self #same as 'class << Hi'
self #=> #<Class:Hi>
self == Hi.singleton_class #=> true
end
end
[faz self == thing.singleton_class
no contexto de seu bloco] .
hi = String.new
def hi.a
end
hi.class.instance_methods.include? :a #=> false
hi.singleton_class.instance_methods.include? :a #=> true
hi
herda objeto seus #methods
a partir da sua #singleton_class.instance_methods
e, em seguida, a partir da sua #class.instance_methods
.
Aqui demos hi
's única classe método de instância :a
. Poderia ter sido feito com a classe << oi .
hi
's #singleton_class
tem todos os métodos de instância hi
' s #class
tem, e, possivelmente, um pouco mais ( :a
aqui).
[métodos de instância de coisa #class
e #singleton_class
podem ser aplicados diretamente a coisa. quando ruby vê thing.a, primeiro procura: uma definição de método em thing.singleton_class.instance_methods e depois em thing.class.instance_methods]
A propósito - eles chamam a classe singleton do objeto == metaclass == eigenclass .
Um método singleton é um método definido apenas para um único objeto.
Exemplo:
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
Métodos de SingClon de SomeClass
teste
Métodos de singleton de test_obj
test_2
test_3
De fato, se você escrever qualquer extensão C para seus projetos Ruby, na verdade, existe apenas uma maneira de definir um método Module.
rb_define_singleton_method
Eu sei que esse negócio próprio apenas abre todos os tipos de outras perguntas para que você possa fazer melhor pesquisando cada parte.
Objetos primeiro.
foo = Object.new
Posso criar um método para foo?
Certo
def foo.hello
'hello'
end
O que eu faço com isso?
foo.hello
==>"hello"
Apenas outro objeto.
foo.methods
Você obtém todos os métodos Object, além do seu novo.
def foo.self
self
end
foo.self
Apenas o objeto foo.
Tente ver o que acontece se você criar foo de outros objetos como classe e módulo. É bom brincar com os exemplos de todas as respostas, mas você precisa trabalhar com idéias ou conceitos diferentes para realmente entender o que está acontecendo com a maneira como o código é escrito. Então agora você tem muitos termos para analisar.
Singleton, Class, Module, self, Object e Eigenclass foram criados, mas Ruby não nomeia Object Models dessa maneira. É mais como Metaclass. Richard ou __por que mostra a idéia aqui. http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html E se você ficar impressionado, tente pesquisar o Ruby Object Model na pesquisa. Dois vídeos que eu conheço no YouTube são Dave Thomas e Peter Cooper. Eles também tentam explicar esse conceito. Dave demorou muito tempo para obtê-lo, então não se preocupe. Eu ainda estou trabalhando nisso também. Por que mais eu estaria aqui? Obrigado pela sua pergunta. Também dê uma olhada na biblioteca padrão. Possui um módulo Singleton, assim como um FYI.
Isso é muito bom. https://www.youtube.com/watch?v=i4uiyWA8eFk