2010-12-31 7 views
14

私は私のプログラムで暗黙の変換、インポートが必要かどうか

object MyString { 
    implicit def stringToMyString(s: String) = new MyString(s)  
} 

class MyString(str: String) { 
    def camelize = str.split("_").map(_.capitalize).mkString 

    override def toString = str 
} 


object Parse { 
    def main(args: Array[String]) { 
    val x = "active_record".camelize 
    // ... 
    } 
} 

を書きます。これにより、コンパイルエラーが発生します。挿入後

import MyString.stringToMyString 

次に動作します。

OverskyのからScalaのプログラミングソースのコンパニオンオブジェクトで暗黙の変換が行われているか、または予想されるターゲットタイプをインポートする必要はありません。

答えて

16

暗黙の変換 ソースのオブジェクトまたは予想される の対象タイプは、である必要はありませんがインポートされました。

ここでメソッドcamelizeはクラスMyStringに定義されていますが、実際にはオブジェクトコンパイル内に暗黙的にMyStringに変換されています。しかし、MyStringターゲットタイプであることをコンパイラに伝えるコードには何もありません。

の場合は、代わりに、あなたはこれを書いた:

val x = ("active_record": MyString).camelize 

それがうまくいく、コンパイラはあなたが"active_record"は、オブジェクトMyString内部の暗黙的な変換を見せること、MyStringことを期待知っているので。

これは少し制限があるように見えるかもしれませんが、実際には数多くの場所で機能します。

class Fraction(num: Int, denom: Int) { 
    ... 
    def +(b: Fraction) = ... 
    ... 
} 

をそしてあなたは、このようなコードだった:今

val x: Fraction = ... 
val y = x + 5 

を、xはその期待タイプFractionある+方法を、持っています。例えば、あなたが持っていた、と言いますしたがって、コンパイラは、オブジェクトFraction内のIntからFractionへの暗黙的な変換(ここではオブジェクトがある場合はInt、そのソースタイプなので、Int)を探します。

13

この状況では、コンパイラはcamelizeメソッドをどこから抜き出したのかコンパイラがわからないため、インポートが必要です。タイプがクリアされている場合、それは輸入せずにコンパイルされます:

object Parse { 
    def foo(s: MyString) = s.camelize 

    def main(args: Array[String]) { 
    val x = foo("active_record") 
    println(x.toString) 
    } 
} 

Martin's articleに基づいて、Pimp my library patternを参照してください。

トップレベルでDEFSを置くことはできませんので、あなたができることに注意してください」グローバルスコープで暗黙の変換を定義する。解決策は、他の輸入品と一緒に、各ソースファイルの先頭にすなわち

object Implicits { 
    implicit def listExtensions[A](xs : List[A]) = new ListExtensions(xs) 
} 

そして、オブジェクトの内側DEFを配置し、それをインポートすることです:

import Implicits._ 
+1

IIRCあなたは、パッケージオブジェクトにインポートを置くことができます。これは、少なくとも「グローバル」なものです:-) – Landei

0

私はそのコンパニオンオブジェクトに暗黙の方法を入れて、Scalaの本の中でプログラミングにおける合理的なクラスの例を試してみました:

object Rational { 
    implicit def intToRational(num: Int) = 
    new Rational(num) 
} 

が、コード

2 + new Rational(1, 2) 

は動作しません。コンバージョンが発生するには、単一の識別子ルールが適用されます。つまり、コンパニオンオブジェクトで定義されていても、明示的なメソッドをスコープにインポートする必要があります。

関連する問題