2016-11-21 9 views
2

は、ここに私の問題です。もし私がFloatCallerを追加したいのであれば、その実装は同じでも、parseEntityを書き直さなければならないでしょう。Scalaの暗黙と上書きの問題

CallerにparseEntityのインプリケーションを書き込むことができます。そのため、子の特性に同じコードを繰り返し書き込む必要はありません。

免責事項: これは、私がSprayJsonSupportで持っている実際の問題を簡略化したもので、akka.http.scaladsl.marshallers.sprayjsonです。

答えて

4

Callerのインスタンスを作成できるファクトリメソッドを使用する方がよいでしょう。 IntCallerDoubleCallerの間で異なるのは、toInttoDoubleです(もちろん種類もあります)。

trait Caller { 
    type EntityType 
    def parseEntity(entity: String): EntityType 
} 

object Caller { 
    def apply[A](f: String => A): Caller = new Caller { 
     type EntityType = A 
     def parseEntity(entity: String): EntityType = f(entity) 
    } 
} 

scala> val IntCaller = Caller(_.toInt) 
scala> IntCaller.parseEntity("123") 
res1: IntCaller.EntityType = 123 

scala> val DoubleCaller = Caller(_.toDouble) 
scala> DoubleCaller.parseEntity("1.23") 
res2: DoubleCaller.EntityType = 1.23 

継承を使用し続けたい場合は、parseEntityとの変換を実装するために、サブクラスや特性を強制し続けています。ただし、暗黙のコンバージョンを使用する必要はありません。繰り返しコードがある唯一の理由は、暗黙的な変換によってparseEntityが実際には(暗黙的に解決する必要があるため)同じであるように見えるためです。

trait Caller { 
    type EntityType 
    def parseEntity(entity: String): EntityType 
} 

trait IntCaller { 
    type EntityType = Int 
    def parseEntity(entity: String): EntityType = entity.toInt 
} 
関連する問題