2016-07-25 1 views
1

J'ai un trait qui fait ce qui suit:Abstracting Comportement commun avec traits Scala

trait MyTrait[T] { 
    def doSomething(elems: Seq[T]) 
} 

J'ai alors une usine qui créerait des instances des mises en œuvre de ce trait:

object MyTrait { 
    def apply(): MyTrait = { 
    new StringTrait() 
    } 
} 

maintenant l'implémentation concrète ressemble à ceci:

class StringTrait extends MyTrait[String] { 
    def doSomething(elems: Seq[String]) = { 
    // some generic logic here 
    // some specific logic here (this code bit depends on the type of implementation) 
    // some generic logic here 
    } 
} 

Comment pourrais-je maintenant faire StringTrait tel que je passe dedans comportement spécifique de lui et ayant la logique générique définie dans une classe abstraite? Une façon serait de passer le comportement en tant que thunk, mais cela signifierait que je dois modifier ma méthode doSomething (...) pour prendre un paramètre supplémentaire que je préférerais éviter.

Répondre

0

Vous avez quelques options, à titre d'illustration, je suppose que le comportement spécifique au type est un Seq [T] => T (ie vous prenez une Séquence de T et vous obtenez un T):

héritage basé:

trait MyTrait[T] { 
    def doTypeSpecificStuff(a: Seq[T]): T 

    def doSomething(elems: Seq[T]): T = { 
    // generic code stuff 
    val t: T = doTypeSpecificStuff(elems) 
    // more generic code 
    t 
    } 
} 

class StringTrait extends MyTrait[String] { 
    def doTypeSpecificStuff(elems: Seq[String]) = { 
    elems.reduceOption(_ + _).getOrElse("") 
    } 
} 

def client(thing: MyTrait[String], elems: Seq[String]) { 
    thing.doSomething(elems) 
} 

type de classe:

trait MyTypeClass[T] { 
    def doTypeSpecificStuff(a: Seq[T]): T 
} 

object StringTypeClass { 
    implicit val instance: StringTypeClass = new StringTypeClass() 
} 

class StringTypeClass extends MyTypeClass[String] { 
    def doTypeSpecificStuff(elems: Seq[String]): String = { 
    elems.reduceOption(_ + _).getOrElse("") 
    } 
} 

object TypeClassDependentBehaviour { 
    def doSomething[T](elems: Seq[T])(implicit tp: MyTypeClass[T]): T ={ 
    //some code 
    val stuff: T = tp.doTypeSpecificStuff(elems) 
    //more generic code 
    stuff 
    } 
} 

def client(elems: Seq[String]) { 
    TypeClassDependentBehaviour.doSomething(elems) 
}