1

特定の変更不可能な Java クラスのセットを簡単に操作できるように、いくつかの Scala 暗黙関数を定義しています。次の Scala コードは単純化された例ですが、明らかにクレイジーに見えます。現実の世界では、次のようなさまざまなメソッドで使用するために、Monkey、Tree、Duck から特定のリソース (年齢の数値ではなく) を暗黙的に取得しようとしていますpurchaseCandles()

// actually 3 Java classes I can not change:
case class Monkey(bananas: Int) 
case class Tree(rings: Int)
case class Duck(quacks: Seq[String])

// implicits I created to make my life easier...
implicit def monkey2Age(monkey: Monkey): Int = monkey.bananas / 1000
implicit def tree2Age(tree: Tree): Int = tree.rings
implicit def duck2Age(duck: Duck): Int = duck.quacks.size / 100000

// one of several helper methods that I would like to define only once,
// only useful if they can use an implicit parameter.
def purchaseCandles()(implicit age: Int) = {
  println(s"I'm going to buy $age candles!")
}

// examples of usage
{
  implicit val guest = Monkey(10000)

  purchaseCandles()
}

{
  implicit val guest = Tree(50)

  purchaseCandles()
}

{
  implicit val guest = Duck(Seq("quack", "quack", "quack"))

  purchaseCandles()
}

3 回発生するコンパイラ エラー:

could not find implicit value for parameter age: Int 
purchaseCandles()
               ^

このサンプル コードが狂っているさまざまな方法はさておき、私の本当の疑問は、暗黙の値の暗黙の変換が Scala の暗黙のパラメーターを満たすことができるかということです。

4

2 に答える 2

5

短い答え:いいえ。Scala のコンパイラは、単一の暗黙の適用のみに目を向けますimplicit int

ただし、purchaseCandlesに変換できる型を操作するメソッドを作成しInt、その型のパラメーターを必要とすることができます。

def purchaseCandles[A <% Int]()(implicit age : A) = {
  val asAge : Int = age
  println(s"I'm going to buy $asAge candles!")
}

このasAge部分は、暗黙的な変換の適用を強制するために必要です。

現時点では、このシナリオでは の型を指定する必要があるようですが、そのA理由はわかりません: 暗黙的に変換できる型の周りに他の値があってはならないためですInt(これは新しい型で発生します)。同様に、それはの遍在性ではありませんInt。)しかし、あなたはすることができます:

{
  implicit val guest = Monkey(10000)

  purchaseCandles[Monkey]()
}

ただし、この暗黙の使用はおそらく悪い考えです。

于 2013-03-15T11:37:10.983 に答える
2

実際にそれを行うことができます:暗黙的な変換のパラメーターも暗黙的にマークするだけです:

implicit def monkey2Age(implicit monkey: Monkey): Int = monkey.bananas / 1000
implicit def tree2Age(implicit tree: Tree): Int = tree.rings
implicit def duck2Age(implicit duck: Duck): Int = duck.quacks.size / 100000

これにより、必要な方法で暗黙がチェーンされます。

いつものように: 注意してください、それはあなたがしたくない場所でもそうします. ところで、型の暗黙的なパラメーターInt(またはその暗黙的な値) を使用しないことを強くお勧めします。それはあまりにも一般的です。(これはあなたの例とまったく同じだと思います)。

于 2014-12-11T23:26:47.123 に答える