2016-12-13 9 views
1
私はSBTと私のプロジェクトを構築していたという事実とこれを序文必要がありますように私は感じ

をインポートする必要はありません。Scalaは、なぜ私が推定されるタイプ

私の問題は、場合、コンパイル時にメソッドがある限り、私は型推論を使用して、すべてがコンパイル、私はメソッドを呼び出すファイルで、unimportedタイプのものを返す、ということです。いったん私の関数の戻り値で作成したvar/valにインポートされていない型を割り当てようとすると、コンパイラエラーが発生します。

は、私は2つのパッケージに2つのクラスを考えてみましょう。パッケージlibrariesパッケージmainとクラスImportedのクラスApp。さらにより多くの私たちは、メインとこのクラスがインポートされたタイプのオブジェクトを作成するための方法があり、そのパッケージ内のクラスImportedFactoryを持っていることを言うことができます。

このコードはうまくコンパイル:

class App() { 
    // method return object of type Imported 
    val imp = ImportedFactory.createImportedObject() 
} 

これはしません:

class App() { 
    // method return object of type Imported 
    val imp : Imported = ImportedFactory.createImportedObject() 
} 

これはまだ、再び行います

import libraries.Imported 

class App() { 
    // method return object of type Imported 
    val imp : Imported = ImportedFactory.createImportedObject() 
} 

これはかなり奇妙な行動のように思えます。これはコンパイル時に型推論を持つ言語では普通ですか?私は無知のために/ C++に行くまでこれまで気づいていませんか?

は、2つの有効なアプローチ(infered対輸入&明示的な型)のいずれかを他の上の利点/欠点がありますか?

この黒い魔法はありますか、Scalaコンパイラはこれらの控除をむしろ順調に進めていますか?いいえ、それは賢明で冗長ではありません。

答えて

1

ノート:あなたは型推論に基づいている必要がありますどのような種類impコンパイラの数字を出しているval imp = ImportedFactory.createImportedObject()と長期型推論

とのより良い検索結果を得ることができます。どんなタイプのcreateImportObjectが返っても、そのタイプはimpです。あなたが明示的にimpImportedであると述べているval imp : Imported = ImportedFactory.createImportedObject()

。しかし、コンパイラはあなたが... import ... itを使わない限り、それが意味するものを知らない。

両方のアプローチはメリットがあります。

推論されたタイプの

推測されるタイプは、あなたがタイプは明らかであるコードを一緒に投げているときに最適です:

val i = 1 // obviously `i` is an int 
val j = i + 10 // obviously still an int 

それはまた素晴らしいことだし型が書こうとする痛みがあまりにも大きすぎるローカルヴァース/ヴァルの場合

val myFoo: FancyAbstractThing[TypeParam, AnotherTypeParam[OhNoMoreTypeParams]] = ... 
// vs 
val myFoo = FancyThingFactory.makeANewOne() 

パブリックdef/valに推論型を許可した場合、そのメソッドの使用方法を判断するのが難しくなる可能性があります。このため、型の注釈を省略するのは、通常、単純な定数、および "クライアントコード"を見る必要のないローカルのvals/varsでのみ使用されます。

明示的なタイプ

あなたは(すなわち、公共ヴァルス/ defsの)ライブラリっぽいコードを書きたいんは、規則は、それらを明示的に入力することです。

このため、おそらくこのための最も簡単な理由がある:あなたがless-を公開したい場合

def myLibraryMethod = { 
    // super complicated implementation 
} 

は、もう一つの利点は、あなたのコードを明示的に入力する

def myLibraryMethod: String = { 
    // super complicated implementation 
} 

より理解することが困難ですが

val invalidNumbers: Set[Int] = TreeSet(4, 8, 15, 16, 23, 42) 

この例では、あなたのinvalidNumbersが実際にはTreeSetであることに気をつける必要があるでしょう。これは実装の詳細です。この場合、実際には気を散らすような情報を隠しています。

5

インポートするのは、現在のスコープで完全修飾名を使用できないことだけです。

あなたimport libraries.Importedがお書きにするための短い名前Importedを利用可能にするためである理由:あなたは、同様にこれを書くことができます。コンパイラに型を推測させる場合は、コードに型を記述しないので、その短い名前をインポートする必要はありません。

ところで、これはC++の動的キャストとは関係ありません。あなたのコードで働く唯一のメカニズムは型推論です。

+0

私はダイナミックキャスティングという用語を流用しましたが、それは実際に私の質問に関するかなりの混乱(および提案の欠如)を引き起こしている可能性があります。 – George

関連する問題