将特征添加到类中的参数类型



我有一个库,其中abstract class Base[T]位于用户提供的T类型之上。有许多特定的Base[T]子类,有些是TS类型,如Specific[T, S],但这无关紧要。用户当然可以在创建和实例时指定任何T,但我想将其视为具有特征AdditionalAbilities T,或者换句话说,我想用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一起使用。

定义参数化类时,可以要求参数类型从特定类型派生:

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

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

以下编译和打印: 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,这就是为什么我制作了私有 doSomethingExtra 方法,该方法将 TAdditional 作为参数。如果我们在"doSomething"中调用能力和附加,那么当我们尝试访问 #ability 和 #additional 时,将创建单独的TAdditional实例,并且将打印"0"。

相关内容

最新更新