otra - ¿Cómo puede una clase anidada acceder a un método en la clase externa en Ruby?
meter una clase dentro de otra java (6)
¿Se suponía que era un método de clase para la clase A
?
class A
def self.a
raise "hi"
end
class B
def b
A::a
end
end
end
A::B.new.b
Si desea mantenerlo como un método de instancia, obviamente tendrá que llamarlo en una instancia, como por ejemplo A.new.a
def class A
def a
raise "hi" #can''t be reached
end
class B
def b
a() #doesn''t find method a.
end
end
end
Quiero invocar a de b y levantar la excepción. ¿Cómo puedo?
Bueno, dependiendo de tus circunstancias, en realidad hay una solución, bastante fácil. Ruby permite la captura de llamadas a métodos que no son capturadas por el objeto. Así que para tu ejemplo podrías hacer:
def class A
def a
raise "hi" #can''t be reached
end
class B
def initialize()
@parent = A.new
end
def b
a() #does find method a.
end
def method_missing(*args)
if @parent.respond_to?(method)
@parent.send(*args)
else
super
end
end
end
end
Entonces si haces esto:
A::B.new().b
usted obtiene:
!! #<RuntimeError: hi>
Probablemente es una forma más fácil de hacer algo como un SubController que solo maneja ciertas actividades, pero que puede llamar fácilmente a los métodos básicos del controlador (aunque desearía enviar el controlador principal como un argumento en el inicializador).
Obviamente, esto debe usarse con moderación, y puede llegar a ser confuso si lo usa en todo el lugar, pero puede ser realmente bueno simplificar su código.
Esto es solo para el lulz:
class A
def a
puts "hello from a"
end
class B
def b
Module.nesting[1].new.a()
end
end
end
Normalmente hago algo como esto:
class A
def a
puts "hi"
end
def createB
B.new self
end
class B
def initialize(parent)
@parent=parent
end
def b
@parent.a
end
end
end
A.new.createB.b
Ruby no tiene clases anidadas.
La única forma de heredar el comportamiento es, bueno, a través de la herencia.
Si desea que su código funcione, necesita usar un idioma que admita clases anidadas. Si bien esta es una característica increíblemente nítida y potente, desafortunadamente solo conozco dos idiomas que tienen clases anidadas:
No sé de ningún otro.
Java tiene una construcción llamada clases anidadas, pero tienen algunas limitaciones de diseño desafortunadas.
En su ejemplo anterior, no es la clase B
que está anidada dentro de A
, es la constante B
que está anidada dentro de A
Piensa sobre esto:
C = A::B
Ahora, la clase está disponible bajo dos nombres: A::B
y C
Debe ser inmediatamente obvio que C
es global y no está anidado dentro de A
(Bueno, en realidad, C
está anidado dentro de Object
, porque tampoco hay realmente constantes globales, pero eso no es lo importante). Pero como C
y A::B
son la misma clase, obviamente no puede ser anidada ni anidada . La única conclusión lógica es que la clase en sí no está anidada.
La característica definitoria de las clases anidadas es que la búsqueda de métodos se realiza a lo largo de dos dimensiones: hacia arriba en la cadena de herencia y hacia afuera a través del anidamiento. Ruby, como el 99.9% de todos los idiomas OO, solo admite el primero. (En cierto sentido, las clases anidadas heredan no solo las características de su superclase, sino también las características de la clase que las rodea).
Si desea que la clase anidada extienda la clase externa, entonces hágalo:
class Outer
class Inner < Outer
def use_outer_method
outer_method("hi mom!")
end
end
def outer_method(foo)
puts foo
end
end
foo = Outer::Inner.new
foo.use_outer_method #<= "hi mom"
foo.outer_method("hi dad!") #<= "hi dad"