2016-11-05 14 views
3

汎用戻り型の関数を記述しようとしましたが、戻り型をキャストしない限り動作しません。以下の関数getSomething()を見てください。私はそれがキャストなしで動作することを期待していました。私はここで何が間違っていますか?scala generic関数戻り型

trait Sup 

class Sub extends Sup { 
    def getString = "I am Sub" 
} 

class Sub2 extends Sup { 
    def getInt = 100 
} 

def getSomething[A <: Sup](str: String) : A = { 
    str match { 
    case "sub" => getSub.asInstanceOf[A] 
    case "sub2" => getSub2.asInstanceOf[A] 
    } 
} 

def getSub(): Sub = { 
    new Sub 
} 

def getSub2() : Sub2 = { 
    new Sub2 
} 

val x = getSomething[Sub]("sub").getString 
val y = getSomething[Sub2]("sub2").getInt 

答えて

1

Alexeyが言及しているように、予想される型と返されるオブジェクトの型の間のリンクを強制するには、instanceOfが必要です。 「コンパイラ、私を信頼してください。私はあなたに「A」を与えています。正しいタイプを提供することは私たちに依存しているので、あまり安全ではありません。

タイプシステムが私たちのために物事を把握したい場合は、追加情報を与える必要があります。 Scalaでそれを行う1つの方法は、型のインスタンスを生成する方法を知っているいくつかのファクトリと、そのファクトリが特定の型を返すことを可能にする証拠を定義することです。

これは、このような構造を導入し、ContextBoundsを使用して、必要なタイプの正しいファクトリインスタンスを取得するためのコードのバージョンです。

trait Sup 

class Sub extends Sup { 
    val str = "I'm a Sub" 
} 

class Sub2 extends Sup { 
    val number = 42 
} 

trait SupProvider[T <: Sup] { 
    def instance:T 
} 

object SupProvider { 
    def getSomeSup[T<:Sup:SupProvider]: T = implicitly[SupProvider[T]].instance 
    implicit object SubProvider extends SupProvider[Sub] { 
    def instance = new Sub 
    } 
    implicit object Sub2Provider extends SupProvider[Sub2] { 
    def instance = new Sub2 
    } 
} 

SupProvider.getSomeSup[Sub].str 
// res: String = I'm a Sub 

SupProvider.getSomeSup[Sub2].number 
// res: Int = 42 
1

asInstanceOfのエラーメッセージは、間違っていることを正確に伝えます。 case "sub"では、本文はSubであり、ASubというスーパータイプであると考えられる理由がありません。Subは暗黙的にAに変換されます。

と仮定します。その後、次の呼び出しは、法的次のようになります。

val z = getSomething[Sub]("sub2").getString 

または

trait Sub3 extends Sup 
val w = getSomething[Sub3]("sup") 

のいずれかの場合にはどうしますか?

関連する問題