成らぬは人の為さぬなりけり

エンジニアライフをエンジョイする為のブログ

メソッド引数とコンストラクタ引数のimplicitパラメータ

最近ずっとHaskellの話題だったんですが、今日はScalaです。

最近少しずつ仕事でもScalaを使うようになってきて、
勉強しなおしてます。

早速表題の件ですが、

class Hoge(val name:String)
class Foo(implicit hoge:Hoge)

implicit val hoge = new Hoge("hoge")
val foo = new Foo

そもそもこんな事がしたい事がありまして、
いろいろ事情があって、
コンパニオンオブジェクトを作って、
applyメソッドを実装してみよう、という事になりました。

結果、このようなコードを書いてみました。

object Foo { 
  def apply(implicit hoge:Hoge) = new Foo 
}

これを、こうすると、エラーになりました。

scala> Foo()
<console>:12: error: not enough arguments for method apply: (implicit hoge: Hoge)Foo in object Foo.
Unspecified value parameter hoge.
              Foo()
                 ^

うーん、、、newの時は

scala> new Foo
res6: Foo = Foo@5b080f38

scala> new Foo()
res7: Foo = Foo@ddb1fe0

大丈夫なのに、applyメソッドはダメなの??
と思い、色々試した結果、

object Foo { 
  def apply()(implicit hoge:Hoge) = new Foo 
}

このようにしたら出来ました。

scala> Foo()
res8: Foo = Foo@61e90abf

ちなみに、そもそもFooをcaseクラスにする事でも実現はできました。

scala> case class Foo(implicit hoge:Hoge)
defined class Foo

scala> Foo()
res9: Foo = Foo(Hoge@728edb84)

うーん、コンストラクタとメソッドでimplicitパラメータの仕様が違うのか??

ちょっと試してみました。

scala> def bar(implicit hoge:Hoge) = hoge.name
bar: (implicit hoge: Hoge)String

scala> bar
res10: String = hoge

scala> bar()
<console>:11: error: not enough arguments for method bar: (implicit hoge: Hoge)String.
Unspecified value parameter hoge.
              bar()
                 ^

なるほど、、、そうなんですね。
でも、これって何故こうなんでしょうか?

続きは明日以降に調べてみます、、、