2016-11-21 1 views
2

Hier ist mein Problem:Scala implicits und Überschreibungen Probleme

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")) 
    } 

} 

Wie man sehen kann ich zu wiederholen halten Sie den Code für: parseEntity Methode. Wenn ich eine FloatCaller hinzufügen wollte, müsste ich parseEntity neu schreiben, obwohl seine Implementierung die gleiche wäre.

Wie kann ich die Implementierung der parseEntity in die Caller schreiben, damit ich nicht immer wieder den gleichen Code in die Kindmerkmale schreiben muss?

Haftungsausschluss: Dies ist eine Vereinfachung eines echten Problems, das ich mit SprayJsonSupport von akka.http.scaladsl.marshallers.sprayjson habe.

Antwort

4

Sie wären besser dran mit einer Factory-Methode, die Instanzen einer Caller mit einer Konvertierungsfunktion erstellen kann. Die einzige Sache, die zwischen IntCaller und DoubleCaller unterschiedlich ist, ist toInt und toDouble (und die Typen natürlich).

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 

Wenn Sie die Vererbung behalten möchten verwenden, dann weiterhin die Unterklassen oder Eigenschaften zu zwingen, die Umwandlung mit parseEntity zu implementieren. Es ist jedoch nicht unbedingt notwendig, implizite Konvertierungen zu verwenden. Der einzige Grund, warum es scheint, dass es wiederholten Code gibt, ist, dass die implizite Konvertierung parseEntity für jede Implementierung gleich aussehen lässt, obwohl es wirklich nicht ist (weil es ein anderes implizites auflösen muss).

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

trait IntCaller { 
    type EntityType = Int 
    def parseEntity(entity: String): EntityType = entity.toInt 
} 
Verwandte Themen