回答:
メソッドのオーバーロードは、名前が同じでシグネチャが異なる2つのメソッドを宣言することで実現できます。これらの異なる署名は、
method(int a, int b) vs method(String a, String b)
method(a) vs method(a, b)
ruby(動的型付き言語)にはデータ型宣言がないため、最初の方法ではメソッドのオーバーロードを実現できません。したがって、上記のメソッドを定義する唯一の方法はdef(a,b)
2番目のオプションでは、メソッドのオーバーロードを実現できるように見えるかもしれませんが、できません。引数の数が異なる2つのメソッドがあるとします。
def method(a); end;
def method(a, b = true); end; # second argument has a default value
method(10)
# Now the method call can match the first one as well as the second one,
# so here is the problem.
そのため、rubyはメソッドルックアップチェーン内の1つのメソッドを一意の名前で維持する必要があります。
「オーバーロード」は、Rubyでは意味をなさない用語です。これは、基本的には、「静的引数に基づく派遣」の同義語ですが、Rubyはありません持っている静的なディスパッチをまったく。つまり、Rubyが引数に基づく静的ディスパッチをサポートしないのは、静的ディスパッチ(ピリオド)をサポートしないためです。引数ベースであろうとなかろうと、それはいかなる種類の静的ディスパッチもサポートしません。
さて、実際にオーバーロードについて具体的に尋ねているのではなく、動的な引数ベースのディスパッチについて多分尋ねている場合、答えは次のとおりです。Matzが実装していないためです。他の誰もそれを提案することに悩まなかったので。他の誰もそれを実装することに悩まなかったからです。
オプションの引数と可変長引数リストを持つ言語で一般的な、ダイナミックな引数に基づく派遣では、ある非常に権利を取得するのは難しい、とさえ難しく理解し、それを維持します。静的な引数ベースのディスパッチがあり、オプションの引数を持たない言語(Javaなど)であっても、どの過負荷が選択されるのかを単なる人間に伝えることはほとんど不可能です。
C#では、あなたが実際にエンコードすることができる任意の C#でのオーバーロードの解決はNP困難であることを意味オーバーロードの解決へ3-SAT問題を。
次に、動的ディスパッチでそれを試してみてください。頭に留めておく時間ディメンションが追加されています。
「非表示」のゼロ番目のself
引数でのみディスパッチするオブジェクト指向言語とは対照的に、プロシージャのすべての引数に基づいて動的にディスパッチする言語があります。たとえば、Common Lispは、動的な型、さらにはすべての引数の動的な値をディスパッチします。Clojureは、すべての引数の任意の関数をディスパッチします(BTWは非常にクールで非常に強力です)。
しかし、動的な引数ベースのディスパッチを備えたオブジェクト指向言語については知りません。マーティン・オーダーズキーは、彼がいることを言ったかもしれないけど、スカラ座への引数ベースのディスパッチを追加することを検討してのみ、彼は同時に過負荷を取り除くことができればとの両方の用途が過負荷状態にし、Javaと互換性のあることをScalaのコードを既存との下位互換性がある(彼は特にSwingとAWTを述べましたJavaのかなり複雑なオーバーロードルールのほとんどすべての厄介な暗い隅のケースを実行するいくつかの非常に複雑なトリックを実行します)。私は引数ベースのディスパッチをRubyに追加することについて自分自身でいくつかのアイデアを持っていますが、下位互換性のある方法でそれを行う方法を理解することはできませんでした。
def method(a, b = true)
ないため、メソッドのオーバーロードは不可能です」ほど単純ではありません。そうではありません; それはただ難しいです。しかし、私はこの答えが本当に有益であることを発見しました。
私はあなたがこれを行う能力を探していると思います:
def my_method(arg1)
..
end
def my_method(arg1, arg2)
..
end
Rubyはこれを別の方法でサポートします。
def my_method(*args)
if args.length == 1
#method 1
else
#method 2
end
end
一般的なパターンは、ハッシュとしてオプションを渡すことです。
def my_method(options)
if options[:arg1] and options[:arg2]
#method 2
elsif options[:arg1]
#method 1
end
end
my_method arg1: 'hello', arg2: 'world'
それが役に立てば幸い
メソッドのオーバーロードは、静的型付けを備えた言語で意味があり、異なるタイプの引数を区別できます。
f(1)
f('foo')
f(true)
だけでなく、引数の数の間
f(1)
f(1, 'foo')
f(1, 'foo', true)
最初の区別はルビーには存在しません。Rubyは動的型付けまたは「ダック型付け」を使用します。2番目の違いは、デフォルトの引数または引数を操作することで処理できます。
def f(n, s = 'foo', flux_compensator = true)
...
end
def f(*args)
case args.size
when
...
when 2
...
when 3
...
end
end
これは、なぜrubyにメソッドのオーバーロードがないのかという質問には答えませんが、サードパーティのライブラリがそれを提供できます。
contracts.rubyのライブラリがオーバーロードできます。チュートリアルからの変更例:
class Factorial
include Contracts
Contract 1 => 1
def fact(x)
x
end
Contract Num => Num
def fact(x)
x * fact(x - 1)
end
end
# try it out
Factorial.new.fact(5) # => 120
これは実際にはJavaのオーバーロードよりも強力であることに注意してください。これは1
、単に型ではなく、一致する値(など)を指定できるためです。
ただし、これを使用するとパフォーマンスが低下します。許容範囲を決定するには、ベンチマークを実行する必要があります。
質問の理由については、すでにすばらしい答えがあります。ただし、他のソリューションを探している人がElixir パターンマッチング機能に触発されたfunction-ruby gemをチェックアウトする場合。
class Foo
include Functional::PatternMatching
## Constructor Over loading
defn(:initialize) { @name = 'baz' }
defn(:initialize, _) {|name| @name = name.to_s }
## Method Overloading
defn(:greet, :male) {
puts "Hello, sir!"
}
defn(:greet, :female) {
puts "Hello, ma'am!"
}
end
foo = Foo.new or Foo.new('Bar')
foo.greet(:male) => "Hello, sir!"
foo.greet(:female) => "Hello, ma'am!"