以前Rubyでoverloadをするという記事を書きました。 この記事で紹介しているoverloader gemを使うとRubyでオーバーロードができるようになります。
overloader gemは今まで引数の数の違いでしかオーバーロードを定義できませんでしたが、v0.2.0で型情報を使用してオーバーロードを定義できるようにしたので、改めて紹介しようと思います。
Installation
まず、型の機能を使うにはRuby 2.7以上を使う必要があります。 そしてruby-signature gemを別途インストールする必要があります。 ruby-signatureは記事執筆時点ではまだRubyGems.orgにpublishされていないので、git cloneしてインストールしてください。
$ git clone https://github.com/ruby/ruby-signature $ bundle install $ bundle exec rake install
そしてoverloader gemも忘れずにインストールしましょう。こちらはRubyGems.orgからインストールできます。
$ gem install overloader
Usage
メソッド定義の前の行にそのメソッドの型情報をコメントで書くと、その型情報を使ってオーバーロードが定義されます。
require 'overloader' require 'overloader/type' class A extend Overloader overload do # (String, Integer) -> untyped def foo(x, y) 'str int' end # (Integer, String) -> untyped def foo(x, y) 'int str' end # (Symbol, Symbol) -> untyped def foo(x, y) 'sym sym' end end end a = A.new p a.foo('bar', 42) # => "str int" p a.foo(42, 'baz') # => "int str" p a.foo(:a, :b) # => "sym sym" p a.foo(:a, 42) # => ArgumentError
この通り、各メソッド呼び出しの引数の型によって呼ばれるメソッドが振り分けられるようになっています。
そして型が合わない引数を渡した場合にはArgumentError
が出るようになっています。
Implementation
ruby-signature自体のテストに使われている、実行時に型検査を行う仕組みをそのまま流用しています。
メソッドに渡されてきた引数をコメントで書いた型定義と突き合わせて、型に合う引数が渡っていたら該当のメソッドを呼び、でなければ次の型を検証する、と言った実装になっています。
overloader gemではむずかしいことはしていないので、興味がある方はぜひコードを読んでみてください。 https://github.com/pocke/overloader/blob/v0.2.0/lib/overloader/type/checker.rb