対象:
JRuby

オーバーロードされているJavaのメソッドを明示的に呼び出す

JRubyからJavaオブジェクトを利用しているとき、オーバーロード(メソッド名が同じで引数が異なる)されているメソッドをうまく呼び出せなかったことはないだろうか。例えば、以下のコードではArrayList内のindex = 1の要素である"2"を削除したいのか、あるいはindex = 2の要素である"3"を削除したいのかという意図とは関係なく、index = 2の"3"が削除される。

require "java"

al = java.util.ArrayList.new

al.add(1) # index = 0
al.add(2) # index = 1
al.add(3) # index = 2

al.remove(2)

al.to_array.each do |item|
  p item
end

実行結果は以下である。つまり、JRubyはArrayListのremove(int index)メソッドを呼び出したのである。

[mobile@localhost ruby]$ jruby overload_test.rb
1
2

しかし、この動作だと"2"という要素を指定してremoveすることはできない。呼び出したいのはremove(Object o)メソッドである。JRuby 1.4以降では、java_methodメソッドを使うと利用したいメソッドを明示的に呼び出すことができる。

require "java"

al = java.util.ArrayList.new

al.add(1) # index = 0
al.add(2) # index = 1
al.add(3) # index = 2

# java_method :メソッド名, [引数型リスト]
remove = al.java_method(:remove, [java.lang.Object])
remove.call(2) # 2を渡してremoveメソッド呼び出し

al.to_array.each do |item|
  p item
end

このとき、java_methodメソッドに渡すメソッド名はRuby風のメソッド名ではなく、Javaのメソッド名であることに注意してほしい。例えば、getDataというメソッドを呼び出す場合、Ruby的にgetを省略して"data"ではなく、"getData"とJavaのメソッド名で記述しなければならない。

Javaオブジェクト.java_method(:Javaメソッド名, [引数の型の配列])

以下が実行結果である。今度はindex = 2の要素ではなく"2"という要素が削除されているのが分かる。

[mobile@localhost ruby]$ jruby overload_test.rb
1
3
(2010/11/25)

新着情報
【オープンソースソフトウェア環境構築】Apple silicon Macで開発環境を構築
【Rust Tips】Actix webでJSONをPOSTする
【Rust Tips】コマンドライン引数を取得する

Copyright(C) 2004-2014 モバイル開発系(K) All rights reserved.
[Home]