2016-11-21 92 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 
}