Classe << Auto -idioma em Ruby
-
22-09-2019 - |
Pergunta
O que class << self
fazer em rubi?
Solução
Primeiro, o class << foo
A sintaxe é aberta foo
Classe de Singleton de Singleton (EigEnclass). 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
a classe singleton, para que os métodos possam ser redefinidos para a corrente self
objeto (que dentro de uma classe ou corpo de módulo é a classe ou módulo em si). Geralmente, 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 em que 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
Então, no exemplo acima, cada instância de StateMachineExample
tem process_hook
aliases para process_state_1
, mas observe como neste último, pode redefinir process_hook
(por self
apenas, não afetando outro StateMachineExample
instâncias) para process_state_2
. Então, cada vez que um chamador liga para o process
Método (que chama o redefinível process_hook
), o comportamento muda dependendo do estado em que está.
Outras dicas
Eu encontrei uma explicação super simples sobre class << self
, Eigenclass
e tipo diferente de methods
nisso blog.
Em Ruby, existem três tipos de métodos que podem ser aplicados a uma classe:
- Métodos de instância
- Métodos Singleton
- Métodos de classe
Os métodos de instância e os métodos de classe são quase semelhantes ao seu homônimo 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 self
qual é a classe Foo
próprio 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
Geralmente, os métodos de instância são métodos globais. Isso significa que eles estão disponíveis em todos os casos da classe em que foram definidos. Por outro lado, um método singleton é implementado em um único objeto.
O Ruby armazena métodos nas classes e todos os métodos devem estar 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 as aulas 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 metaclasses, também conhecidas como aulas de singleton ou eigenclasses. O método Singleton está associado ao metaclasse que, por sua vez, está associado ao objeto no qual o método singleton foi definido.
Se vários métodos de singleton forem definidos em um único objeto, todos serão armazenados no mesmo 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 eu atual para apontar para a metaclasse do objeto Z1; Em seguida, define o método SAY_HELLO dentro da metaclasse.
As 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 de 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 aulas também podem ter metaclasses. No exemplo acima, a classe << se modifica, para que aponte para a metaclasse da classe Zabuton. Quando um método é definido sem um receptor explícito (a classe/objeto em que o método será definido), ele é implicitamente definido no escopo atual, ou seja, o valor atual do eu. Portanto, o método do material é 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 O exemplo acima foi incluído, para que entendamos o que está acontecendo quando encontramos a classe << sintaxe self.
Informações adicionais podem ser encontradas em Este post sobre aulas de rubi.
Que classe << Coisa:
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.
O que é coisa.singleton_class?
hi = String.new
def hi.a
end
hi.class.instance_methods.include? :a #=> false
hi.singleton_class.instance_methods.include? :a #=> true
hi
Objeto herda seu #methods
de seu #singleton_class.instance_methods
e então de seu #class.instance_methods
.
Aqui demos hi
's Classe Singleton método de instância :a
. Poderia ter sido feito com classe << oi em vez de.
hi
's #singleton_class
tem todos os métodos de instância hi
's #class
tem, e possivelmente mais um pouco (:a
aqui).
Métodos de instância de coisa #class
e #singleton_class
pode ser aplicado diretamente à coisa. Quando Ruby vê a coisa.
A propósito - eles chamam de objeto Classe Singleton == metaclasse == Eigenclass.
A. 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 Someclass de Singleton
teste
Métodos de Singleton de test_obj
test_2
test_3
De fato, se você escrever alguma extensão C para seus projetos de rubi, existe realmente apenas uma maneira de definir um método de módulo.
rb_define_singleton_method
Sei que esse auto -negócio abre todos os tipos de outras perguntas para que você possa fazer melhor pesquisando cada parte.
Objetos primeiro.
foo = Object.new
Posso fazer um método para foo?
Claro
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 de objeto mais o seu novo.
def foo.self
self
end
foo.self
Apenas o objeto foo.
Tente ver o que acontece se você fizer foo de outros objetos, como classe e módulo. Os exemplos de todas as respostas são bons de brincar, 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 procurar.
Singleton, Classe, Module, Self, Objeto e Eigenclass foram criados, mas Ruby não nomeia modelos de objetos dessa maneira. É mais como Metaclass. Richard ou __lha que mostra a ideia aqui.http://viewsourcecode.org/why/hacking/seeingmetaclassclearly.htmlE se o derrubar, tente procurar um modelo de objeto Ruby na pesquisa. Dois vídeos que eu conheço no YouTube são Dave Thomas e Peter Cooper. Eles tentam explicar esse conceito também. Dave levou muito tempo para obtê -lo, então não se preocupe. Ainda estou trabalhando nisso também. Por que mais eu estaria aqui? Obrigado pela sua pergunta. Dê uma olhada também na biblioteca padrão. Possui um módulo singleton como um FYI.
Isso é muito bom.https://www.youtube.com/watch?v=i4uiywa8efk