在类中添加特征到参数类型

时间:2015-04-23 19:54:42

标签: scala generics traits parametric-polymorphism

我有一个库,其中abstract class Base[T]超过了用户提供的类型T。有许多特定的Base[T]子类,有些是类型TS,类似Specific[T, S],但这是无关紧要的。用户可以在创建和实例时指定任何T当然,但我想将其视为具有特征T的{​​{1}},或者换句话说我想要“礼物”用户的类型与AdditionalAbilities。我怎么能在Scala中做到这一点?我希望这个问题的标题是正确的。

示例(可能在语法上不正确)

AdditionalAbilities

适用于任何class Specific[T **with trait Additional**]() extends Base[T](){ def doSomething() : T = { val something = new T() something.ability(2) println(something.additional) something } } trait Additional{ var additional : Integer def ability(i : Integer) : Unit = { additional = i } }

2 个答案:

答案 0 :(得分:1)

定义参数类时,可以要求参数类型从某种类型下降:

trait AdditionalAbilities {
  def doStuff(): Unit = println("Hey There")
}

object NoAbility extends AdditionalAbilities {
  override def doStuff(): Unit = ()
}

abstract class Base[T] { ... }

class Specific[T <: AdditionalAbilities] extends Base[T] {
  def f(t: T): Unit = t.doStuff()
}

然后当您尝试实例化Specific类型时:

scala> new Specific[Int] {}
<console>:13: error: type arguments [Int] do not conform to class Specific's type parameter bounds [T <: AdditionalAbilities]

scala> val b = new Specific[NoAbility.type] {}
b: Specific[NoAbility.type] = $anon$1@517cd4b

scala> b.f(NoAbility)
//did nothing

此外,如果要向现有的具体类添加行为,可以在实例化时执行此操作:

trait CoolAbilities { def doStuff(): Unit = println("Hey there") }
class A { }

scala> val a = new A with CoolAbilities
a: A with CoolAbilities = $anon$1@6ad3381f

scala> a.doStuff()
Hey there

答案 1 :(得分:0)

也许隐式课可能会有所帮助?隐式类允许您向现有类型添加功能而无需修改现有类型,或者是实例化它(以便您可以混合使用特征)。

以下编译并打印:3

class Specific[T] {
  implicit class TAdditional(t: T) {
    var additional: Integer = 0
    def ability(i: Integer) = {
      additional = i
    }
  }

  def doSomething(t: T) = {
    doSomethingAdditional(t)
  }

  private def doSomethingAdditional(t: TAdditional) = {
    t.ability(3)
    println(t.additional)
  }
}

val s = new Specific[Int]
s.doSomething(5)

注意:我们需要做些什么来确保我们访问同一个实例 TAdditional,这就是我制作私有的doSomethingAdditional方法的原因,该方法将TAdditional作为参数。如果我们在“doSomething”中调用“能力”和“附加”功能,则在我们尝试访问#ability和#additional时会创建单独的TAdditional实例,并且&#39; 0&#39;会被打印出来。