Scala动态实例化。如何传递必须扩展某些特征的参数

时间:2016-10-19 16:48:40

标签: scala inheritance manifest traits

我正在学习scala并创建了一个foo条形码来玩耍特性和Manifest。这是我的目标用途:

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

这是我的代码:

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)
  }
}

我得到的当前错误是speak[Foo *with Style]错误']'预期,但'找到'。

如何确保类型推断出必须使用样式扩展Foo的类

2 个答案:

答案 0 :(得分:2)

这不会起作用......

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

... 1st因为你已经定义speak()没有参数,而第2因为MilitarySlang不在范围内(即从呼叫网站看不到)。

一个简单的解决方案(可能过于简单)是将Style从类型参数移动到值参数。

Foo内,定义变为def speak(style: Style, subject: String): String,而Slang内的定义变为...... {/ p>

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

...可以像这样调用......

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

答案 1 :(得分:1)

您可以将Style拆分为单独的特征,但在Foo中使用自我类型。

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

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

这将告诉编译器任何扩展Foo的东西都必须用Style扩展它。