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

La sintaxis anterior se utiliza para definir 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 usa para cualquier otro tipo de definiciones. Mi punto de confusión aquí es la siguiente:En Ruby hay aplicaciones relacionadas de la sintaxis: class << self ... end

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 se agrega eso para "poner los contenidos 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 un contexto de clase < < 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 

Respuesta

18

en Ruby puede volver a abrir las clases existentes y agregar 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 Foo -class (que es sólo una instancia de la Class -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 instancias de objetos existentes

foo = Foo.new 
foo2 = Foo.new 

def foo.fred 
    return "I am fred" 
end 


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

pero ¿Dónde se almacena realmente este método?

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

Así que la relación de herencia se ve así:

foo < (eigenclass of foo) < Foo < Class 

(si usted dice foo.superclase no verá la clase singleton)

class << X -sintaxis es una forma de llegar a esta clase especial, para que pueda manipularla 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. (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) para k es un método ejemplo de los eigenclass de Foo, lo que lo convierte en un método de la clase para Foo

todo esto se explica con mayor claridad en el chapter about classes of the Pickaxe (la versión web no contiene los diagramas, por desgracia) y _whys Seeing Metaclasses Clearly

2

pienso en la clase que contiene un diccionario de miembros que incluye todos los descriptores de acceso y variables de instancia. Cuando le dices a la clase que "añada" a "sí mismo", estás diciendo "agrégalos al diccionario de los miembros de la clase".

Aunque concederé que la notación es un poco extraña.

+0

Ok - que' Es una buena forma de ver que la clase es en realidad un diccionario. Pero en realidad usted respondió antes de agregar mi último ejemplo, donde en otro contexto el mismo sintaxis (según el libro que estoy leyendo) produce métodos de clase en lugar de métodos de instancia de clase. ¿Por qué el ejemplo de la clase Punto en la parte inferior da como resultado un método de clase, mientras que attr_accessor en la parte superior le proporciona atributos que están en el nivel de instancia de clase? –

+0

En realidad, usando la explicación que me dio quizás pueda responder a la pregunta en mi comentario anterior: el método attr_accessor llama a los métodos instance_variable_set y instance_variable_get de la clase Class. Normalmente, eso daría como resultado la creación de variables de instancia, pero como estamos agregando al diccionario de la clase, como usted dice, estamos creando variables de instancia de clase. Ok, creo que lo tengo ahora. Gracias. –

+1

-1 engañoso, ya que la clase << x ... end en realidad agrega información a la metaclase de x, no a la clase de x. – rampion

1

es realmente confuso pensar en términos de un operador "agregar". una mejor manera de verlo es que al igual que class Foo se abre la clase Foo, es decir, se establece 'a sí mismo' en el objeto de clase Foo, creándolo si es necesario, de modo que class << self abre la clase propia del objeto 'propio' actual. tenga en cuenta que no se limita a sí mismo: para cualquier barra de objetos, puede decir la clase < < para abrir la clase 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 
Cuestiones relacionadas