使用Ruby处理抽象类解决方案的正确方法是什么?

时间:2016-02-20 20:28:57

标签: ruby oop object-oriented-analysis

我知道抽象类不是Ruby中的一个特性,当然背后有一个哲学原因,但我想知道是否有办法解决通常使用其他语言(如C ++和C ++)中的抽象类来解决的问题。 Java的。

例如: 我需要三个课程TriangleSquareCircle。因为这些都是几何图形,所以我在考虑用抽象方法AbstractFigure编写一个名为get_area的抽象类,它将由具体类TriangleSquare实现。 ,和Circle

我如何按照Ruby哲学做到这一点?

3 个答案:

答案 0 :(得分:7)

你是正确的,它并不像红宝石那样在一个明确定义的概念中存在,不像其他语言,如Java,它被大量使用。

但是你也很正确,有很多情况需要它。

以下是我用你的例子 -

的方式
class AbstractShape
  attr_accessor :edges

  def initialize
    # ...
  end

  def get_area
    raise NoMethodError("Override this implementation")
  end
end


class Square < AbstractShape
   def initialize
     # square-specific stuff
     super
   end

   def get_area
     self.edges * foo * bar
   end
end

关键是要在顶层定义所有可用的方法以提高可读性和一致性,但如果使用它们,请确保它们引发错误。

如果有一种绝对确定的方法将在所有形状中以相同的方式使用,那么在AbstractShape

中定义它

attr_accessor也将继承,因此您可以针对每个形状在每个实例的基础上提供@edges。但是你仍然可以在AbstractShape类中引用引用@edges的方法,因为它们只会使用正确的本地实例变量。

答案 1 :(得分:3)

使用方法AbstractFigure定义普通类get_area,只需引发NotImplementedError。然后,每个派生类都会使用它自己的实现覆盖get_area方法。

class AbstractFigure
    def get_area
        raise NotImplementedError.new( 'appropriate error message' )
    end
end

class Square < AbstractFigure
    def get_area
        # implementation here
    end
end

答案 2 :(得分:0)

使用Class::newModule#const_set

k = Class.new do
      def area(width, height)
        width*height
      end
    end

["A", "B"].each { |sub| Object.const_set(sub, Class.new(superclass=k)) }
  #=> ["A", "B"]

class A
  def perimeter(width, height)
    2*(width+height)
  end
end

A.superclass
  #=> #<Class:0x007fd26a05d5b8> 
B.superclass
  #=> #<Class:0x007fd26a05d5b8> 
A.instance_method(:area).owner
  #=> #<Class:0x007fd26a05d5b8> 
A.new.area(3,4)
  #=> 12 
A.new.perimeter(5,10)
  #=> 30 
k.new.area(2,5)
  #=> 10