如何在Scala中将方法参数限制为子类类型 [英] How to restrict method parameter to subclass type in Scala
问题描述
我有一个特征 GameStatistics
,它定义了一个 add()
方法,该方法接受一个参数并返回其自身和该参数的和.子类中的实现应仅接受其自身类型的实例作为参数(或者也可以是子类型).
I have a trait GameStatistics
that defines an add()
method that takes a parameter and returns the sum of itself and the parameter. Implementations in subclasses should only accept instances of their own type as a parameter (or maybe also subtypes).
我想使用此 add
方法,通过Seq的 reduce
方法来汇总 GameStatistics
的列表.
I would like to use this add
method to aggregate lists of GameStatistics
, using Seq's reduce
method.
我无法在Scala中定义它并进行编译.下面是我尝试过的一个示例及其编译错误.
I have not been able to define this in Scala and make it compile. Below is one example that I tried plus its compile errors.
这些错误对我没有任何意义.我应该如何使它工作?
The errors don't make any sense to me. How should I get this to work?
package bgengine
trait GameStatistics {
def equity: Double
def add[G: this.type](s: G): G
def multiply(x: Double): GameStatistics
}
object GameStatistics {
def aggregate(stats: Seq[GameStatistics]): GameStatistics = stats.reduce( _ add _ )
}
case class SimpleGameStatistics(equity: Double, nrGames: Int) extends GameStatistics {
override def add[G: SimpleGameStatistics](s: G): G =
SimpleGameStatistics((equity * nrGames + s.equity * s.nrGames) / (nrGames + s.nrGames), nrGames + s.nrGames).asInstanceOf[G]
override def multiply(x: Double): SimpleGameStatistics = SimpleGameStatistics(equity * x, nrGames)
}
错误:(6,12)GameStatistics.this.type没有类型参数
def add [G:this.type](s:G):G
Error:(6, 12) GameStatistics.this.type does not take type parameters
def add[G: this.type](s: G): G
错误:(17,21)bgengine.SimpleGameStatistics没有采用类型参数覆盖def add [G:SimpleGameStatistics](s:G):G =
Error:(17, 21) bgengine.SimpleGameStatistics does not take type parameters override def add[G: SimpleGameStatistics](s: G): G =
错误:(18,48)值资产不是类型参数G的成员SimpleGameStatistics((equity * nrGames + s.equity * s.nrGames)/(nrGames + s.nrGames),nrGames + s.nrGames).asInstanceOf [G]
Error:(18, 48) value equity is not a member of type parameter G SimpleGameStatistics((equity * nrGames + s.equity * s.nrGames) / (nrGames + s.nrGames), nrGames + s.nrGames).asInstanceOf[G]
错误:(18,59)值nrGames不是类型参数G的成员SimpleGameStatistics((equity * nrGames + s.equity * s.nrGames)/(nrGames + s.nrGames),nrGames + s.nrGames).asInstanceOf [G]
Error:(18, 59) value nrGames is not a member of type parameter G SimpleGameStatistics((equity * nrGames + s.equity * s.nrGames) / (nrGames + s.nrGames), nrGames + s.nrGames).asInstanceOf[G]
错误:(18,83)值nrGames不是类型参数G的成员SimpleGameStatistics((equity * nrGames + s.equity * s.nrGames)/(nrGames + s.nrGames),nrGames + s.nrGames).asInstanceOf [G]
Error:(18, 83) value nrGames is not a member of type parameter G SimpleGameStatistics((equity * nrGames + s.equity * s.nrGames) / (nrGames + s.nrGames), nrGames + s.nrGames).asInstanceOf[G]
错误:(18,105)值nrGames不是类型参数G的成员SimpleGameStatistics((equity * nrGames + s.equity * s.nrGames)/(nrGames + s.nrGames),nrGames + s.nrGames).asInstanceOf [G]
Error:(18, 105) value nrGames is not a member of type parameter G SimpleGameStatistics((equity * nrGames + s.equity * s.nrGames) / (nrGames + s.nrGames), nrGames + s.nrGames).asInstanceOf[G]
推荐答案
You probably want
<:
(subtype) instead of:
(context bound).
this.type
doesn't mean what you think it means (it is the type which only has this
(and null
) as value, not "the current type").
如果您解决了这些问题,则投射
If you fixed those problems, the cast in
override def add[G <: SimpleGameStatistics](s: G): G =
SimpleGameStatistics((equity * nrGames + s.equity * s.nrGames) / (nrGames + s.nrGames), nrGames + s.nrGames).asInstanceOf[G]
没有道理;您刚刚创建了 SimpleGameStatistics
的实例,将其强制转换为子类将引发异常.
wouldn't make sense; you just created an instance of SimpleGameStatistics
, casting it to a subclass would throw an exception.
但是您似乎想要 F界多态性:>
But it looks like you want F-bounded polymorphism:
trait GameStatistics[G <: GameStatistics[G]] { this: G =>
def equity: Double
def add(s: G): G
def multiply(x: Double): G
}
object GameStatistics {
def aggregate[G <: GameStatistics[G]](stats: Seq[G]): G = stats.reduce( _ add _ )
}
case class SimpleGameStatistics(equity: Double, nrGames: Int) extends GameStatistics[SimpleGameStatistics] {
override def add(s: SimpleGameStatistics): SimpleGameStatistics =
SimpleGameStatistics((equity * nrGames + s.equity * s.nrGames) / (nrGames + s.nrGames), nrGames + s.nrGames)
override def multiply(x: Double): SimpleGameStatistics = SimpleGameStatistics(equity * x, nrGames)
}
这篇关于如何在Scala中将方法参数限制为子类类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!