¿Cómo puedo forzar una subclase para implementar un método en Ruby? No parece haber una palabra clave abstracta en Ruby, que es el enfoque que tomaría en Java. ¿Hay alguna forma más similar a Ruby para hacer cumplir el resumen?Método abstracto en Ruby
Respuesta
Se supone que los métodos abstractos son menos útiles en Ruby porque no es
fuertemente
estáticamente tipado.
Sin embargo, esto es lo que hago:
class AbstractThing
MESS = "SYSTEM ERROR: method missing"
def method_one; raise MESS; end
def method_two; raise MESS; end
end
class ConcreteThing < AbstractThing
def method_one
puts "hi"
end
end
a = ConcreteThing.new
a.method_two # -> raises error.
Rara vez parece ser necesaria, sin embargo.
Ruby está fuertemente tipado. Simplemente no está tipado estáticamente. –
Siempre me sale mal. Ta, editado. – Andy
+1, así es como se hace en Smalltalk con 'subclassResponsibility' ('^self subclassResponsibility'). –
Mi enfoque preferido es similar pero ligeramente diferente ... lo prefiero como sigue, porque hace que el código de auto-documentado, que le da algo muy similar a Smalltalk:
class AbstractThing
def method_one; raise "SubclassResponsibility" ; end
def method_two; raise "SubclassResponsibility" ; end
def non_abstract_method; method_one || method_two ; end
end
Algunas personas se quejan de que esto es menos SECO e insiste en crear una subclase de excepción y/o poner la cadena "SubclassResponsibility"
en una constante, pero en mi humilde opinión you can dry things up to the point of being chafed, and that is not usually a good thing. P.ej. si tiene múltiples clases abstractas en su base de código, ¿dónde definiría la constante de cadena MESS
?!?
¿Qué tal un beat em con un símbolo :)? Entonces es una constante que flota alrededor, no una cadena en cada caso. Me gusta tu respuesta – baash05
única objeción, es que las clases secundarias tendrían que implementar no_abstract_method también, de lo contrario cuando se llamara (presumiblemente para probar), se llamaría al método uno y se podría llamar al método 2. – baash05
me gusta el uso de una joya como abstract_method que da una conexión DSL de sintaxis estilo rieles métodos abstractos:
class AbstractClass
abstract_method :foo
end
class AbstractModule
abstract_method :bar
end
class ConcreteClass < AbstractClass
def foo
42
end
end
me gusta la respuesta por pvandenberk, pero me gustaría mejorarlo de la siguiente manera:
module Canine # in Ruby, abstract classes are known as modules
def bark
fail NotImplementedError, "A canine class must be able to #bark!"
end
end
Ahora si usted hace una clase que pertenece a Canine
"clase abstracta" (es decir, una clase que tiene el módulo Canine
en sus antepasados), se quejará si se encuentra que el método #bark
no está implementado:
class Dog
include Canine # make dog belong to Canine "abstract class"
end
Dog.new.bark # complains about #bark not being implemented
class Dog
def bark; "Bow wow!" end
end
# Now it's OK:
Dog.new.bark #=> "Bow wow!"
Tenga en cuenta que ya que las clases de Ruby no son estáticas, sino que siempre abierta a los cambios, Dog
clase en sí no puede hacer cumplir existencia de #bark
métodos, ya que no sabe cuándo se supone que debe ser terminado. Si usted como programador lo hace, le corresponde a usted probarlo en ese momento.
Este código no le permitirá cargar la clase si los métodos 'foo', 'bar' y 'mate' no están definidos en la clase heredada.
No tiene en cuenta las clases que se definen en muchos archivos, pero seamos honestos, ¿muchos de nosotros realmente definen los métodos de clase en muchos archivos? Quiero decir si no cuentas mezclas. (Que esto no cuenta para)
def self.abstract(*methods_array)
@@must_abstract ||= []
@@must_abstract = Array(methods_array)
end
def self.inherited(child)
trace = TracePoint.new(:end) do |tp|
if tp.self == child #modules also trace end we only care about the class end
trace.disable
missing = (Array(@@must_abstract) - child.instance_methods(false))
raise NotImplementedError, "#{child} must implement the following method(s) #{missing}" if missing.present?
end
end
trace.enable
end
abstract :foo
abstract :bar, :mate
Si usted quiere tener produce un error cuando se crea una instancia de la clase que usted podría hacer lo siguiente
class AnstractClass
def self.new(args)
instance = allocate # make memory space for a new object
instance.send(:default_initialize, args)
instance.send(:initialize, args)
instance
end
#This is called whenever object created, regardless of whether 'initialize' is overridden
def default_initialize(args)
self.abstract_method #This will raise error upon object creation
end
private :default_initialize
def initialize(args)
# This can be overridden by new class
end
end
class NewClass < AbstractClass
end
NewClass.new #Throw error
- 1. C# Desechar método abstracto
- 2. ¿Método abstracto o virtual?
- 3. método abstracto de error
- 4. Método abstracto PHP versus método predeterminado
- 5. Declaración de método abstracto - virtual?
- 6. ¿Cómo escuchar un método abstracto?
- 7. Clase/método abstracto, cómo C# -> VB.NET
- 8. Java: Anulando un método abstracto en la subclase
- 9. Java: tipo de retorno polimórfico en un método abstracto?
- 10. Invalidar método abstracto sobre creación de la instancia en C#
- 11. ¿Cómo puedo crear un método en JS como un método abstracto en Java?
- 12. ¿Cómo puedo determinar si se implementa un método abstracto?
- 13. El método tiene que ser anulado pero no es abstracto
- 14. Está imponiendo una implementación de método abstracto unpythonic?
- 15. Método abstracto C# con implementación de clase base solamente?
- 16. Definir un método abstracto sin especificar los parámetros
- 17. Método abstracto que devuelve una instancia de clase derivada
- 18. ¿Debe una clase abstracta tener al menos un método abstracto?
- 19. C++: Crear clase abstracta con método abstracto y anular el método en una subclase
- 20. Método de acceso en Ruby
- 21. Punteros de método en ruby
- 22. El método 'upto' en Ruby
- 23. Método Flatten Ruby en C#
- 24. ¿Existe algo demasiado "abstracto"?
- 25. Ruby: método indefinido `> '
- 26. Ruby isPrime Método
- 27. Ruby Detect método
- 28. Patrón de fábrica abstracto
- 29. Tipo abstracto devuelto en la clase base
- 30. En Java, ¿cuándo debería usar un método abstracto en una interfaz?
Además, Ruby utiliza algo llamado Typing Pato: http://en.wikipedia.org/wiki/Duck_typing – mikeycgto
@delnan, no hubo necesidad de expresar su respuesta de esa manera. Si estuviera tratando de mantenerme en una mentalidad Java, no estaría pidiendo una solución tipo "Ruby". Gracias, sin embargo, por su sugerencia sobre la excepción de tiempo de ejecución. –
Lo siento si salí grosero. Acabo de ver * tantas * personas tratando de programar en el lenguaje A como si fuera el lenguaje B.Tu pregunta también se parecía un poco a esto, cuando preguntaste cómo hacer lo que las clases abstractas hacen en Java (en lugar de "un rubí equivalente a clases abstractas" o algo así como likr zhsz). Nuevamente, sin ofenderse, quizás te equivoqué. – delnan