What is preferable for strategies in scala: object or property

I usually use traits to implement strategies (some actions that do not require accompanying fields). I recently discovered that the same functionality can be defined in terms of objects. They can directly expand a functional attribute or extend some feature that defines special methods, except apply ()

Code example:

/* strategy realization via traits */ package object Traitness { trait Strategy { def performAction() : Unit = () } abstract class Usage {_ : Strategy => def doWork() = this.performAction() } // defining strategies trait SayA extends Strategy { override def performAction() = { println("A") super.performAction() } } trait SayB extends Strategy { override def performAction() = { println("B") super.performAction() } } trait SayC extends Strategy { override def performAction() = { println("C") super.performAction() } } //using strategies class SimpleStrategy extends Usage with SayA def reverseOrder() = new Usage with SayC with SayA object fullUsage extends Usage with SayA with SayB with SayC //run-time checking val check1 : Boolean = (new SimpleStrategy).isInstanceOf[SayB] val check2 : Boolean = reverseOrder().isInstanceOf[SayB] val check3 : Boolean = fullUsage.isInstanceOf[SayB] //compile-time checking def proclaim(x : SayB) = println("SayB") } /* strategy realization via function objects */ package object Valueness { trait Strategy extends Function0[Unit] class Usage(val strategies : List[Strategy]) { def doWork() = for (s <- strategies) s() } //defining strategies object SayA extends Strategy { override def apply() = { println("A") } } object SayB extends Strategy { override def apply() = { println("B") } } object SayC extends Strategy { override def apply() = { println("C") } } //using strategies class SimpleStrategy extends Usage(SayA :: Nil) def reverseOrder() = new Usage(SayB :: SayA :: Nil) val fullUsage = new Usage(SayA :: SayB :: SayC :: Nil) //run-time checking def check(strategy : Strategy, usage : Usage) = usage.strategies contains strategy val check1 : Boolean = check(SayB, new SimpleStrategy) val check2 : Boolean = check(SayB, reverseOrder()) val check3 : Boolean = check(SayB, fullUsage) //no compile-time checking available } 

Which one to choose?

+4
source share
2 answers

In your case, using either traits or objects, this is an unnecessary object-oriented excess. Your strategies are simply functions and can be implemented as cleanly as possible.

 object Strategy{ type Strategy = () => Unit val sayA:Strategy = ()=>{println("A")} val sayB:Strategy = ()=>{println("B")} val sayC:Strategy = ()=>{println("C")} } 

Subclassing Function0 [Unit] here just doesn’t buy you anything, and it costs you the opportunity to create trivial literals. Functions are great objects in Scala. Get involved with them and feel free to use them directly.

+4
source
 class MyStrategy { val sayABC: Strategy.Strategy = () => { Strategy.sayA() Strategy.sayB() Strategy.sayC() } } reflect.runtime.universe.typeOf[MyStrategy].members.filter(_.asTerm.fullName.endsWith(".sayABC")).head 

Result:

 res36: reflect.runtime.universe.Symbol = value sayABC 

If my sayABC function consists only of calls to various functions, it would be nice if someone showed us how to get these calls to say A, say B, sayC through AST?

... it should be a well-formatted response to Dave Griffith's code

0
source

All Articles