Scala:按存储元素的类型匹配vararg(重复参数)



我最近开始学习Scala,目前正在忙于教程。我想要两个Rational算术的实现。我有特性IRational和两个实现它的类:Rational和RationalAbstraction。大多数功能都是相同的,所以我在trait中实现了默认行为,但我需要获得正确的构造函数——无论是Rational还是RationalAbstraction。为此,我有一个功能:

def constructorImpl(numerator: Int, denominator: Int, first: IRational, irationals: IRational*): IRational = {
println(s"first class: ${first.getClass.getSimpleName}, irationals class: ${irationals.getClass.getSimpleName}")
first match {
case rational: Rational => irationals match {
case rationals: Seq[Rational] => new Rational(numerator, denominator)
case _ => throw new UnimplementedCaseException(this, "constructorImpl", first +: irationals: _*)
}
case abstraction: RationalAbstraction => irationals match {
case abstractions: Seq[RationalAbstraction] => new RationalAbstraction(numerator, denominator)
case _ => throw new UnimplementedCaseException(this, "constructorImpl", first +: irationals: _*)
}
case _ => throw new UnimplementedCaseException(this, "constructorImpl", first +: irationals: _*)
}
}

不幸的是,它不起作用
case rationals: Seq[Rational] => new Rational(numerator, denominator)
不匹配包含Rational的varargs,也允许理性抽象
为什么?如何按类型匹配varargs
我需要一个接一个地编写打开irationals:_*的函数并检查头(第一个元素(的类型吗?

这是项目github存储库:https://github.com/axal25/LearnScalaMavenBasics

调用函数测试用例[256行]:https://github.com/axal25/LearnScalaMavenBasics/blob/master/src/main/scala/org/exercises/scala/ool/ObjectOrientedProgramming.scala

功能实现[106行]:https://github.com/axal25/LearnScalaMavenBasics/blob/master/src/main/scala/org/exercises/scala/ool/arith/ration/IRational.scala

如果有人有一些很好的示例材料(教程(来说明这些该死的讨厌的varargs是如何在Scala中工作的,我将不胜感激。

编辑:
constructorImpl方法的目的是为算术运算(add/+,sub/-.mul/*,div//(选择正确的构造函数
first: Irational参数是操作的第一个参数(add、sub、mul、div(
irationals: Irational*自变量为第2、第3、。。。操作的第n个参数(add、sub、mul、div(
有些操作需要2个IRational实现对象,有些操作需要1个IRationalimpl对象。和例如Int,但总是至少1个IRational impl对象。因此,选择正确的构造函数取决于那些IRational impl对象,并要求它们都具有相同的实现。如果IRational实现的两个(或更多(对象是不同的实现(Rational和RationalAbstraction的组合(,我们不知道该调用什么构造函数,所以应该抛出异常。

这个层次结构中的解决方案(不使用泛型(:

def constructorImpl(numerator: Int, denominator: Int, first: IRational, irationals: IRational*): IRational = {
println(s"first class: ${first.getClass.getSimpleName}, irationals class: ${irationals.getClass.getSimpleName}")
@scala.annotation.tailrec
def isSeqElementsOfTypeSameAsFirst(first: Any, irationals: Any*): Boolean = irationals match {
case Seq() => true
case Seq(head, tail@_*) => {
if (first.getClass == head.getClass) isSeqElementsOfTypeSameAsFirst(first, tail: _*)
else false
}
case _ => false
}
if (isSeqElementsOfTypeSameAsFirst(first, irationals: _*)) {
first match {
case rational: Rational => new Rational(numerator, denominator)
case abstraction: RationalAbstraction => new RationalAbstraction(numerator, denominator)
case _ => throw new UnimplementedCaseException(this, "constructorImpl", first +: irationals: _*)
}
}
else throw new MixingIRationalImplementationException(first, irationals: _*)
}

问题提交:https://github.com/axal25/LearnScalaMavenBasics/commit/c5a113b0361d8632bb39bbfc7ed7f7cd329a2da1
解决方案提交:https://github.com/axal25/LearnScalaMavenBasics/commit/1920128ba2aedac4fa9671311ec56dcc09dc7483

我需要写一个函数来逐个打开irationals:_*并检查头(第一个元素(的类型吗?

是的,您需要检查每个元素。irationals可以包含IRational的任何子类的元素,它们不必都是同一个子类,因此需要检查每一个子类。但目前尚不清楚irationals的目的是什么,因此这个问题需要更多的细节。

最新更新