23

私は、透過的な implicit変換が本当に良いアイデアであるかどうか、そして暗黙的により多くの、ええと、明示的に使用する方が実際に良いのではないかと考えてきました。たとえば、パラメータとしてaを受け入れるメソッドがあり、 aを:にDate変換する暗黙の変換があるとStringします。Date

implicit def str2date(s: String) : Date = new SimpleDateFormat("yyyyMMdd").parse(s)

private def foo(d: Date)

次に、明らかにこれを透過的なimplicit変換で呼び出すことができます。

foo("20090910")

文字列を日付に変換しているという事実をより明確にする方がよいでしょうか?

class DateString(val s: String) { 
  def toDate : Date = new SimpleDateFormat("yyyyMMdd").parse(s) 
}

implicit def str2datestr(s: String) : DateString = new DateString(s)

したがって、使用法は次のようになります。

foo("20090910".toDate)

これの利点は、後で何が起こっているのかがより明確になることです-私は(誰かに?)implicit知っておくべき透過的な変換によって数回捕らえられましたが、この使用法はまだ私たちがの力を利用することを可能にしますs。OptionIterableimplicit

4

2 に答える 2

44

少なくともこの例では、暗黙的な変換を行うより「明示的な」方法は、完全に透過的な方法よりも読みやすさの点ではるかに優れていると思います。

私の意見では、タイプ間でimplicit完全に透過的にsを使用することは、タイプのオブジェクトが必要なときにいつでも使用できるものとしてAタイプのオブジェクトを常に表示Bできる場合は問題ありません。たとえば、aからaへの暗黙の変換は常に意味があります。aは常に、概念的には文字のシーケンスと見なすことができます(たとえば、Cでは、文字列は単なる文字のシーケンスです)。の呼び出しは、すべての人にとって意味があります。ABStringRandomAccessSeq[Char]Stringx.foreach(println) String

一方、タイプのオブジェクトをタイプのオブジェクトとして使用Aできる場合Bは、より明示的な変換を使用する必要があります。あなたの例では、への呼び出しfoo("bar")は意味がなく、エラーをスローします。Scalaは例外をチェックしていないため、への呼び出しはfoo(s.toDate)、例外がスローされた可能性があることを明確に示します(s有効な日付ではない可能性があります)。また、foo("bar".toDate)明らかに間違っているように見えますが、なぜ間違っているのかを確認するにはドキュメントを参照する必要がありますfoo("bar")。Scala標準ライブラリでのこの例は、ラッパーのメソッドを介したsからStringsへの変換です( sはsと見なすことができますが、常にではありません)。InttoIntRichStringStringInt

于 2009-09-10T12:47:57.390 に答える
13

XからYへの暗黙の変換(上記の文字列から日付への変換など)を行う場合、基本的には、最初にXの書き込みを完全に制御できた場合、Xを実装するか、 Yのサブクラス。

XがYを実装することが理にかなっている場合は、変換を追加します。そうでない場合は、おそらくそれは適切ではありません。たとえば、StringがRandomAccessSeq [Char]を実装することは理にかなっていますが、StringがDateを実装することは意味がないかもしれません(StringDateを実装するStringは問題ないようですが)。

(私は少し遅れており、Flaviuは優れた答えを持っていますが、暗黙についての考え方についてコメントを追加したいと思います。)

于 2009-09-12T22:04:33.403 に答える