Skip to content

Instantly share code, notes, and snippets.

@ldacosta
Created January 16, 2014 18:47
Show Gist options
  • Save ldacosta/8460909 to your computer and use it in GitHub Desktop.
Save ldacosta/8460909 to your computer and use it in GitHub Desktop.
Let's suppose that I have an abstract trait for which I have 'n' (> 2) concrete implementations. When I mix those traits, I want to have an elegant way to create concrete classes. See below.
// define mixable traits:
trait T
trait T1 extends T
trait T2 extends T
...
trait T100 extends T
// now let's mix them:
trait anotherT extends T
// and create concrete classes.
// THIS IS THE PART NOT COOL. Is there any way to do the following, better?
case class anotherT1 extends anotherT with T1
case class anotherT2 extends anotherT with T2
...
case class anotherT100 extends anotherT with T100
@suhailshergill
Copy link

import org.scalatest.{ BeforeAndAfter, WordSpec }

class foo extends WordSpec with BeforeAndAfter {
  object Test {
    object Traits {
      trait Foo { val foo: Boolean }
      // default setting
      implicit object Foo1 extends Foo { val foo: Boolean = false }
      // non-default
      object Foo2 extends Foo { val foo: Boolean = true }
    }

    object Classes {
      import Traits.Foo
      case class Bar(bar: String = "bar")(implicit imp: Foo) extends Foo {
        val foo: Boolean = imp.foo
      }
    }

    object Uses {
      import Classes._
      val one = Bar()
      val two = Bar()(Traits.Foo2)
    }
  }

  import Test._
  "adhoc" should {
    assertResult(Traits.Foo1.foo)(Uses.one.foo)
    assertResult(Traits.Foo2.foo)(Uses.two.foo)
  }
}

@ldacosta
Copy link
Author

OK, let's see if I understand.

Basically

// we define base trait
trait T { val i: Int }
// and the bunch of guys that extend this: 
scala> object T1 extends T { val i = 1 }
defined module T1
scala> object T2 extends T { val i = 2 }
defined module T2
// ...etc... 
// Now I create concrete classes spinning from this: 
case class anotherTI()(implicit t: T) { val j = t.i }
// We are good; we can do stuff like: 
scala> val x = anotherTI()(t = T1)
x: anotherTI = anotherTI()
scala> x.j
res0: Int = 1

And we are a couple of twists (as you show) we can default values for that implicit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment