2016-11-21 88 views
2

這裏是我的問題:斯卡拉implicits和覆蓋問題

trait Caller { 

    type EntityType 
    def parseEntity(entity: String): EntityType 
} 

trait IntCaller extends Caller { 

    implicit def strToInt(s: String) = s.toInt 
    override type EntityType = Int 
    override def parseEntity(entity: String): EntityType = entity 
} 

trait DoubleCaller extends Caller { 

    implicit def strToDouble(s: String) = s.toDouble 
    override type EntityType = Double 
    override def parseEntity(entity: String): EntityType = entity 
}  

object main { 

    def main(args: Array[String]): Unit = { 
     val intCaller = new IntCaller{} 
     val doubleCaller = new DoubleCaller{} 

     println("Result is: " + intCaller.parseEntity("5")) 
     println("Result is: " + doubleCaller.parseEntity("5.0")) 
    } 

} 

正如你可以看到我不斷重複的代碼爲:parseEntity方法。如果我想添加一個FloatCaller,我將不得不重寫parseEntity,即使它的實現是相同的。

如何在Caller中寫入parseEntity的實現,以便我不必一次又一次地在子特徵中編寫相同的代碼?

免責聲明: 這是一個真正的問題簡化我與SprayJsonSupportakka.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 
}