我有一个库,其中abstract class Base[T]
位于用户提供的T
类型之上。有许多特定的Base[T]
子类,有些是T
和S
类型,如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"。