形状继承示例和“Ruby方式”

时间:2009-07-03 01:54:02

标签: ruby inheritance idioms

在我从十年的C ++过渡到Ruby的过程中,我发现自己第二次猜测如何完成最简单的事情。鉴于下面的经典形状推导示例,我想知道这是否是“The Ruby Way”。虽然我相信下面的代码没有任何本质上的错误,但我仍然觉得我没有充分利用Ruby的全部功能。

class Shape
  def initialize
  end
end

class TwoD < Shape
  def initialize
    super()
  end

  def area
     return 0.0
  end
end

class Square < TwoD
  def initialize( side )
    super()
    @side = side
  end

  def area
    return @side * @side
  end
end

def shapeArea( twod )
  puts twod.area
end

square = Square.new( 2 )

shapeArea( square ) # => 4

这是实施“红宝石之路”吗?如果没有,你会如何实现这个?

2 个答案:

答案 0 :(得分:7)

关于Ruby的美妙之处在于,您不必仅使用继承来提供已实现方法的契约。相反,你可以做到这一点:

class Square
  def initialize(side)
    @side = side
  end

  def area
    @side * @side
  end
end

class Circle
  def initialize(radius)
    @radius = radius
  end

  def area
    @radius * @radius * 3.14159
  end
end

shapeArea(Square.new(2))
shapeArea(Circle.new(5))

这是一种称为鸭子打字的功能。只要twod有一个区域方法(用Ruby的说法,我们会说twod响应区域),你很高兴。

答案 1 :(得分:2)

第一个答案是“红宝石方式”,但是如果你感觉到从C ++(高度打字)到红宝石(鸭子打字)的变化,你可以让它感觉更像家:

class TwoD < Shape
  ...
  def area
    # make this truly look pure-virtual
    raise NoMethodError, "Pure virtual function called"
  end
end

当然,你正在过渡到红宝石,所以你也可以避免重复自己:

class Module
  def pure_virtual(*syms)
    syms.each do |s|
      define_method(s) { raise NoMethodError, "Pure virtual function called: #{s}" }
    end
  end
end

class TwoD < Shape
  pure_virtual :area
  ...
end