2016-08-23 51 views
0

以下のスカラーコードがあります。スーパークラスを持つ関数をパラメータとして持つ関数への引数としてSubclassを渡す関数

trait Super 
case class Sub(value:String) extends Super 
case class YetAnotherSub(value:String) extends Super 
case class OnlyErrorType(value:String) extends Super 

def function1[I <: Super, R](mapper : (I) => R, input: Super) (default: R): R = input match { 
    case error: OnlyErrorType => 
    default 

    case success: I => mapper(success) // Ideally success => mapper(success) 

    case _ => default // I don't want this line at all, as I'm not expecting any other type 
} 

def function2(input:String):Super = if(input.size >= 3) Sub("Greater") else OnlyErrorType("Lesser") 

def function3(input:String):String = { 
    val result = function2(input) 
    function1({sub:Sub => sub.value.toUpperCase}, result) ("Empty Result") 
} 

function3("Input") 

いくつかのパラメータを受け入れ、Superの任意のサブタイプを返すfunction2に似たさまざまな機能があります。私は、function1のように、一般的なマッパーを持っている他のいくつかのタイプにタイプSuperをマッピングするために、私はOnlyErrorTypeのために取り扱い、いくつかのデフォルトを持っていると思いますつまりOnlyErrorType

の場合はデフォルト値を返しますが、聞かせたいと思います呼び出し関数(この場合はfunction3)は、SuccessTypeのマッピングを指定します(サブタイプはSuperOnlyErrorType以外))。

どうすればよいですか?上記のコード

はコンパイルが、私はこれを行うには良い方法がなければならないと思います

warning: abstract type pattern I is unchecked since it is eliminated by erasure 

、警告を見て嫌い。

答えて

1

警告が嫌いです。この場合、基本的にテストが機能しないことを意味します。

最も簡単な方法は、SuccessTypeを明示することです。

sealed trait Super 
trait SuccessType extends Super 
case class Sub(value:String) extends SuccessType 
case class YetAnotherSub(value:String) extends SuccessType 
case class OnlyErrorType(value:String) extends Super 

def function1[R](mapper: SuccessType => R, input: Super) (default: R): R = input match { 
    case _: OnlyErrorType => default 
    case success: SuccessType => mapper(success) 
} 

Superが封入されているので、それは別の場所直接を拡張することはできませんが、そのサブタイプの1つをすることができ、あなたが追加することができます新しいSuccessType秒。それが望ましくない場合はSuccessTypesealedとしてください。 もちろん、この場合function1({case sub:Sub => sub.value.toUpperCase}, result) ("Empty Result")YetAnotherSubが渡された場合に失敗します。それがあなたが望んでいない場合は、 "Super"が成功すればSubと、成功した場合はYetAnotherSub "Super"とを区別する必要があります。あなたは

sealed trait Super[I <: Super[I]] 
case class Sub(value:String) extends Super[Sub] 
case class YetAnotherSub(value:String) extends Super[YetAnotherSub] 
case class OnlyErrorType[I <: Super[I]](value:String) extends Super[I] 

def function1[I <: Super[I], R](mapper : (I) => R, input: Super[I]) (default: R): R = input match { 
    case error: OnlyErrorType[_] => 
    default 

    case success => mapper(success.asInstanceOf[I]) 
} 

def function2(input:String):Super[Sub] = if(input.size >= 3) Sub("Greater") else OnlyErrorType("Lesser") 

def function3(input:String):String = { 
    val result = function2(input) 
    function1({sub:Sub => sub.value.toUpperCase}, result) ("Empty Result") 
} 

function3("Input") 

を使用することができます。しかし、私は希望しないように:function1でキャストが実際に安全であるが、それは自明ので(とSuper間違ってそれを破ることができるの新しいサブタイプを定義する)ではありません。

+0

私は最初の提案がうまくいきました。コンパイルされません。 – nobody

+0

提案を修正しました。 –

関連する問題