3

在我从 C++ 十年过渡到 Ruby 的过程中,我发现自己在猜测如何完成最简单的事情。鉴于下面的经典形状推导示例,我想知道这是否是“红宝石之路”。虽然我相信下面的代码本质上没有任何问题,但我仍然觉得我没有充分利用 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

这是实施的“红宝石之路”吗?如果没有,您将如何实施?

4

2 回答 2

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 有一个 area 方法(用 Ruby 的说法,我们会说 twod 响应 area),你就可以开始了。

于 2009-07-03T02:05:14.113 回答
2

第一个答案是“ruby 方式”,但如果你感觉到从 C++(高度类型化)到 ruby​​(鸭式类型)的变化,你可以让它感觉更像家:

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

当然,您正在过渡到 ruby​​,因此您也可以避免重复自己:

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
于 2009-07-03T13:47:55.923 回答