2009-07-03 9 views
3

C++の10年からRubyへの移行を追求して、私は自分が最も単純なものを達成する方法を2番目に推測していると感じます。以下の古典的な形の導出の例を考えてみましょう。これが "The Ruby Way"かどうか疑問に思っています。下のコードに本質的に間違っていることは何もないと私は思っていますが、私はRubyのフルパワーを利用していないと感じています。シェイプ継承の例と "The Ruby way"

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 

"Ruby Way"は実装されていますか?そうでない場合は、これをどのように実装しましたか?

答えて

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がエリアに応答すると言います)、あなたは良いです。

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 
+0

私はこのようなことを嫌います。最初に 'def area ...'をタイプしないでください。それはすでにメソッドのエラーを発生させます。コメントを追加すると、サブクラスが適切に実装できるように 'area'がどうすべきかを記述する必要があります。 –