Frage

I'm playing around with Scala. I have somethis like this:

trait Test {
  type SweetType

  def methodA(l: String, esc: Boolean): SweetType
  def methodB(a: SweetType): String
}

class MyTest extends Test {

  override type SweetType = (String, Boolean)

  override def methodA(l: String, esc: Boolean): (String, Boolean) = ???

  override def methodB(a: (String, Boolean)): String = ???
}

object Test {
  def apply(): Test = new MyTest()
}

MyTest is a concrete implementation of Test, i would like to keep at trait level without a defintion SweetType, is just design information.

trait SomethingElse {    
  val test:Test
  def methodA(a:test.SweetType):String
}

The concrete implementation of this trait will use what Test provides.

class MySomethingElse extends SomethingElse {
  val test = Test()

  override def methodA(a:test.SweetType):String = test.methodB(a) + "Cuanak"

}

Here is my question, this is scala-legal, but is done right? or i should use a opaque trait or somethis like that? I just want to make referece to any concrete implementation of the abstract type defined in Test "SweetType"

edit i forgot a reference in the trait Test

UPDATE!

For my case works best using the "cake pattern"

trait TestComponent {

  val test:Test

  trait Test {
    type SweetType

    def methodA(l: String, esc: Boolean): SweetType

    def methodB(a: SweetType): String
  }

  class MyTest extends Test {

    override type SweetType = (String, Boolean)

    override def methodA(l: String, esc: Boolean): (String, Boolean) = ???

    override def methodB(a: (String, Boolean)): String = ???
  }

}


trait SomethingElseComponent {
  this :TestComponent =>

  trait SomethingElse {

    def methodA(a:Test#SweetType):String
  }


  class MySomethingElse extends SomethingElse {

    override def methodA(a:Test#SweetType):String = test.methodB(a) + "Cuanak"

  }
}
War es hilfreich?

Lösung

Your code looks well-designed to me. This is a common pattern: a trait with both abstract and concrete members, an object that provides specifics for the abstract members. And, as you observed, you can put a trait abstract val in another trait to aggregate all the abstract members.

This is analogous in math to making abstract structures that relate to other abstract structures:

trait Ring {
  type E
  def add(x: E, y: E): E
  def mul(x: E, y: E): E
  def minus(x: E): E
  val zero: E
  val one: E
}

trait Module {
  val ring: Ring
  import ring._

  type V

  def add(x: V, y: V): V
  def mul(x: E, y: V): V
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top