対象:
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)

新着情報
【iOS Objective-C, Swift Tips】画像の向きを指定して保存する(Swift)
【iOS Objective-C, Swift Tips】UIImagePickerControllerの表示を日本語にする(Swift)
【iOS Objective-C, Swift Tips】ウィンドウの階層構造を3D表示する(Swift)

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