如何在Scala中将方法参数限制为子类类型 [英] How to restrict method parameter to subclass type in Scala

查看:55
本文介绍了如何在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]

推荐答案

  1. 您可能希望使用<:(子类型)而不是:(

  1. You probably want <: (subtype) instead of : (context bound).

this.type 并不代表您的意思(它是

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆