2011-10-04

可変長引数を可変長引数をとるメソッドに渡す

とある Java ライブラリのメソッドをラップしてメソッドを作ろうとしていたときのことです。ラップしたいメソッドは以下の java.lang.String#format のように可変長引数をとるものです。
public static String format(String format, Object... args) 
Scala だと scala.collection.immutable.StringLikeformat みたいなものですね。
def format (args: Any*): String
最初は特に何も考えずに以下のように実装してみました。
object Foo {
  def foo(format: String, args: AnyRef*): String = java.lang.String.format(format + " - foo", args)

  def main(args: Array[String]) {
    println(foo("%s", "Fizz"))
    println(foo("%s, %s", "Fizz", "Buzz"))
  }
}
これ、コンパイルはできますが、1つめの println の出力結果は意図とは異なり、2つめの println では例外が発生します。出力結果は以下のようになります。
WrappedArray(Fizz) - foo
java.util.MissingFormatArgumentException: Format specifier 's'
--- snip ---
出力結果からすると java.lang.String#format の引数に可変長引数ではなく WrappedArray という型で渡っているため意図した結果になっていないようです。
以下のようにすることで可変長引数のまま渡すことが出来ました。
object Foo {
  def foo(format: String, args: AnyRef*): String = java.lang.String.format(format + " - foo", args: _*)

  def main(args: Array[String]) {
    println(foo("%s", "Fizz"))
    println(foo("%s, %s", "Fizz", "Buzz"))
  }
}