1
votes

I'm learning scala and created a foo bar code to play around with traits and Manifest. Here's the usage I'm aiming for:

slang = new Slang()
slang.speak[MilitarySlang]("Private")
slang.speak[GanstaSlang]("Homie")

Here's my code:

trait Foo {
  val foo = "Foo'd Up "
  trait Style {
    def phrase(subject : String): String
  }
  def speak(someone: String): String
}

class Slang extends Foo {

  class MilitarySlang extends Style {
    def phrase(subject: String) = "Beyond All Recognition, " + subject
  }

  class GanstaSlang extends Style {
    def phrase(subject: String) = "Fo Sheezy, " + subject
  }

  def speak[Foo with Style: Manifest](someone: String): String = { 
    val mbar = manifest[Foo with Style].erasure.newInstance().asInstanceOf[Foo with Style]
    foo + mbar.phrase(someone)
  }
}

Current error I get is with speak[Foo *with Style] Error ']' expected but 'with' found.

How do I ensure that the type inferred with a class that MUST EXTEND Foo with Style?

2
But Foo is abstract, and its instance cant be created even by using the manifest route. - Samar

2 Answers

2
votes

This isn't going to work ...

slang = new Slang()
slang.speak[MilitarySlang]("Private")

... 1st because you've defined speak() to take no arguments, and 2nd because MilitarySlang isn't in scope (i.e. not visible from the call site).

One simple solution (perhaps overly simple) is to move Style from a type parameter to a value parameter.

Inside Foo the definition becomes def speak(style: Style, subject: String): String, and inside Slang you'd have ...

def speak(style: Style, subject: String): String =
  foo + style.phrase(subject)

... which can be invoked like so ...

val slang = new Slang
slang.speak(new slang.MilitarySlang, "private")
// res0: String = Foo'd Up Beyond All Recognition, private
1
votes

You might split Style into a separate trait but use a self type in Foo like this.

trait Style {
  def phrase(subject : String): String
}

trait Foo {
  this: Style =>
  val foo = "Foo'd Up "
  def speak(): String
}

This will tell the compiler that anything that extends Foo must extend it with Style.