variable una manejo llamar imprimir ejemplos definicion def clases clase alcance ruby class

manejo - Ruby: alcance explícito en una definición de clase



manejo de clases en ruby (2)

descargo de responsabilidad: Código tomado de los ruby koans

Esto es de una discusión de las constantes de alcance dentro de las clases. Aquí está la definición de un par de clases:

class Animal LEGS = 4 def legs_in_animal LEGS end end class MyAnimals LEGS = 2 class Bird < Animal def legs_in_bird LEGS end end end

En este punto, al hacer MyAnimals::Bird.new.legs_in_bird obtienen 2 y entiendo por qué: buscar en el espacio léxico la constante anterior a la jerarquía de herencia.

Entonces esta clase se define:

class MyAnimals::Oyster < Animal def legs_in_oyster LEGS end end

El tutorial dice que ahora llamar a MyAnimals::Oyster.new.legs_in_oyster da MyAnimals::Oyster.new.legs_in_oyster resultado 4 y no puedo entenderlo. Me parece que Oyster es una clase anidada en MyAnimals y, como tal, esperaba que se comportara de la misma manera que la clase Birds. Me falta información clave sobre lo que significa declarar la clase Oyster con alcance explícito.

¿Puede alguien explicarme esto? He encontrado cientos de tutoriales de ruby ​​class a través de Google pero ninguno de ellos aborda esta situación.

gracias de antemano...


Creo que este ejemplo lo explica mejor. Ruby busca la definición constante en este orden:

  1. El ámbito de cierre.
  2. Cualquier alcance externo (repita hasta que se alcance el nivel superior) Cualquier alcance externo (hasta el nivel superior sin incluirlo)
  3. Módulos incluidos
  4. Superclase
  5. Nivel superior
  6. Objeto
  7. Núcleo

EDITAR

Gracias a Mark Amery por señalar este error. El nivel superior solo se alcanza en el caso de que no haya ámbitos y / o superclases adjuntos. El ejemplo vinculado realmente lo deja claro, lamentablemente lo leí mal.

Un ejemplo para este caso:

FOO = ''I pity the foo!'' module One FOO = ''one'' class Two FOO = ''two'' def self.foo FOO end end class Three < Two def self.foo FOO end end end class Four class Five < Four def self.foo FOO end end end describe FOO do it "depends where it is defined" do expect(FOO).to eq ''I pity the foo!'' # top-level expect(One::FOO).to eq ''one'' # module expect(One::Two.foo).to eq ''two'' # class expect(One::Three.foo).to eq ''one'' # outer scope (One) comes before superclass expect(Four::Five.foo).to eq ''I pity the foo!'' # top-level end end


Si define Oyster INSIDE en la definición de la clase MyAnimals, obtendrá la respuesta que legs_in_oyster es 2.

Si define la Oyster por separado, es decir, la define después de que LEGS = 2 haya quedado fuera del alcance, obtendrá la respuesta de 4.

Esto me sugiere que la clase anidada se comporta de manera diferente a como lo hace un espacio de nombres, tal vez más como un cierre.

---EDITAR---

irb(main):076:0> class MyAnimals::RunningRoach < Animal; def using_legs; LEGS; end; end => nil irb(main):077:0> MyAnimals::RunningRoach.new.kind_of?(MyAnimals) => false irb(main):078:0> MyAnimals::RunningRoach.new.kind_of?(Animal) => true irb(main):081:0> class MyAnimals::Mantis < MyAnimals; def killing_legs; LEGS; end; end => nil irb(main):082:0> MyAnimals::Mantis.new.kind_of?(Animal) => false irb(main):083:0> MyAnimals::Mantis.new.kind_of?(MyAnimals) => true irb(main):084:0> MyAnimals::Mantis.new.killing_legs => 2 irb(main):085:0> MyAnimals::RunningRoach.new.using_legs => 4

De acuerdo con "The Ruby Programming Language", las constantes se buscan en el Ámbito Léxico del lugar donde se usan primero y en la jerarquía de herencia en segundo lugar. Entonces, ¿cuál es el alcance léxico de algo que hereda Animal? El animal en sí, ¿verdad? La clase MyAnimals redefine LEGS, por lo que cualquier cosa que use LEGS, y se define dentro de MyAnimals, buscará LEGS dentro de MyAnimals primero.