如何使子类参数在抽象类中可用以在 Scala 中进行模式匹配?

问题描述 投票:0回答:1

我有一个类和两个案例子类:

abstract class C
case class C1(left: C, right: C, weight: Int) extends C
case class C2(weight: Int) extends C

我想实现如下内容:

def weight(t: C): Int = {
    t match {
      case c1: C1 => l.weight
      case c2: C2 => c2.left.weight + c1.right.weight //this line doesn't let the code compile
    }
  }

以上代码无法编译。说

left
right
没有属性
weight
。我看到这个是因为 C 没有为其定义权重。只有
c1
c2
可以。但是,我传递给
weight
函数的类实例将是
c1
c2
并且肯定会有权重。

它实际上是树上的递归权重求和,我可以通过以下方式实现:

def weight(t: C): Int = {
    t match {
      case c1: C1 => l.weight
      case c2: C2 => weight(c2.left) + weight(c1.left)
    }
  }

但是,我不想递归,如果重量信息在我传入的实例中就可用,我认为我不必这样做。

这是我要解决的作业问题,类

C
C1
C2
的签名是神圣不可侵犯的。我试过修改

abstract class C

abstract class C:
    val weight: Int = ???

但是,这随后开始引发

weight
C1
签名中的
C2
变量的问题,并要求我覆盖它。

我尝试并认为可行的一个解决方案是创建一个伴生对象:

abstract class CodeTree
object CodeTree:
  val weight: Int = ???
case class Fork(left: CodeTree, right: CodeTree, chars: List[Char], weight: Int) extends CodeTree
case class Leaf(char: Char, weight: Int) extends CodeTree

但是我觉得伴生对象不会被子类继承

  • 如何在无需递归的情况下实现预期的结果?
  • 更广泛地说,我如何赋予一个抽象类——这个特定的字段在从我继承的子类中总是可用的,因此它应该对我静态可用并且不会失败编译
scala methods pattern-matching overriding algebraic-data-types
1个回答
1
投票

你应该添加成员

weight: Int
C

abstract class C:
  def weight: Int
case class C1(left: C, right: C, weight: Int) extends C
case class C2(weight: Int) extends C

然后你可以匹配输入的模式

def weight(t: C): Int =
  t match
    case c1: C1 => c1.left.weight + c1.right.weight
    case c2: C2 => c2.weight

或构造函数模式

def weight(t: C): Int = 
  t match 
    case C1(l, r, _) => l.weight + r.weight
    case C2(w) => w

如果类型仅在 Scala 中匹配,为什么我们需要单独的案例标识符?

通常抽象成员是

def
,并在实现中用
def
/
val
/
lazy val
var
如果需要)覆盖。

© www.soinside.com 2019 - 2024. All rights reserved.