0

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

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

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

可以与任何T.

4

2 回答 2

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
于 2015-04-23T20:52:34.727 回答
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,当我们尝试访问#ability和#additional时会创建单独的TAdditional实例,并且会打印'0'。

于 2015-04-23T23:12:18.430 回答