Pregunta

class << self
attr_accessor :n, :totalX, :totalY
end

La sintaxis anterior se utiliza para la definición de las variables de instancia de clase. Pero cuando pienso en lo que implica la sintaxis, no tiene ningún sentido para mí, así que me pregunto si este tipo de sintaxis se utiliza para cualquier otro tipo de definiciones. Mi punto de confusión aquí es la siguiente:

class << self

El operador de agregación normalmente significa "añadir lo que está a la derecha al objeto de la izquierda". Pero en el contexto de este bloque, ¿cómo que se suman a "poner el contenido de este bloque en la definición de la instancia de clase en lugar de la instancia"?

Por la misma razón por la que estoy confundido en cuanto a por qué en una clase de contexto << auto puede definir variables de instancia de clase, mientras que en otro se parece crear variables de clase, como aquí:

class Point
  # Instance methods go here
  class << self
    # Class methods go here
  end
end
¿Fue útil?

Solución

en Ruby puede volver a abrir clases existentes y añadir métodos. Es decir, se puede decir:

class Foo
  def bob
    return "hello from bob"
  end
end

estos métodos se almacenan en algún lugar de un diccionario interno (tal vez una variable de instancia) de la clase Foo (que es sólo una instancia de la clase Class y por lo tanto tiene variables de instancia)

Pero lo más sorprende es que también se puede añadir métodos a casos de los objetos existentes

foo = Foo.new
foo2 = Foo.new

def foo.fred
  return "I am fred"
end


foo.fred  #=> "I am fred"
foo2.fred #=> NoMethodError

y ¿Dónde está este método realmente se almacena

Resulta que Rubí crea una nueva clase detrás de las escenas (a veces llamado clase Singleton , metaclase o eigenclass ), que se inserta en la herencia jerarquía entre de la clase Foo y su ejemplo.

Así que la relación de herencia se parece a lo siguiente:

foo < (eigenclass of foo) < Foo < Class

(si usted dice foo.superclass no verá la clase Singleton)

class << X la sintaxis es una manera de llegar a esta clase especial, por lo que se puede manipular directamente. Los siguientes bloques de código son exactamente equivalentes:

def foo.bar
  return "xy"
end

# is exactly the same as

class << foo
  def bar
    return "xy"
  end
end

Así que la similitud entre class Foo < Bar y class << Foo no es accidental, no hay herencia pasando en ambos.

Piense en class << X como "abrir el metaclase de X"

Lo que hay que recordar en Ruby es que las clases en sí son sólo objetos. (Las instancias de la clase Class) por lo que si dicen:

class Foo
  class << self
    def k
      return "x"
    end
  end
end

(self está obligado a Foo en este bloque de código), de modo k es un método de instancia de los eigenclass de Foo, que hace que sea un método de clase para Foo

todo esto se explica con mayor claridad en el capítulo del acerca de las clases de la piqueta (la versión web no contiene los diagramas, por desgracia) y _whys al ver metaclases Claramente

Otros consejos

Piense en la clase que contiene un diccionario de miembros, incluyendo todos los descriptores de acceso y las variables de instancia. Cuando le dices a la clase de "añadir" a "sí", que dice "agregar estos al diccionario de miembros de la clase."

Te concedo la notación es un poco hinky, sin embargo.

en realidad es confuso para pensar en ella en términos de un operador "añadir". una mejor forma de verlo es que así como class Foo abre clase Foo, es decir, se establece 'sí' al objeto de clase Foo, creando si es necesario, por lo class << self abre las eigenclass del objeto actual 'auto'. en cuenta que no se limita a la auto -. para cualquier barra de objetos, se puede decir que la clase << barra para abrir el eigenclass de ese objeto

class A
  def hello
    print "hello world"
  end
end

a = A.new
b = A.new

class << a
  def goodbye
    print "goodbye cruel world"
  end
end

a.hello
b.hello
a.goodbye
b.goodbye
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top