Scala中如何让抽象类获取子类参数以实现模式匹配?
Scala抽象类子类字段访问与非递归权重计算问题
首先看你定义的抽象类及子类:
abstract class C case class C1(left: C, right: C, weight: Int) extends C case class C2(weight: Int) extends C
你最初尝试的代码存在两处问题:一是case c1: C1分支里的l是未定义变量,应该写c1.weight;二是case c2: C2分支里调用c2.left,但C2类根本没有left成员,这也是编译失败的原因之一。
针对你的两个问题,解答如下:
1. 如何不使用递归实现预期效果?
如果C1的weight字段在创建时就已经包含了左右子树的权重总和,那直接通过模式匹配提取每个子类的weight即可,完全不需要递归:
def weight(t: C): Int = { t match { case C1(_, _, w) => w case C2(w) => w } }
如果C1的weight仅代表自身权重,必须加上左右子树的权重才能得到整体权重,那无法绕过递归——树形结构的权重总和本身就是递归定义的,除非你在创建C1实例时预先计算好完整权重并存在weight字段里,否则必须递归遍历子树求和。
2. 如何让抽象类声明特定字段必然在子类中存在,从而静态可用且不编译失败?
在Scala中,要强制子类实现某个字段,只需在抽象类中定义抽象val(不要给默认值):
abstract class C { val weight: Int // 抽象字段,子类必须实现 } // Case class的参数默认是val,会自动重写抽象字段,无需额外代码 case class C1(left: C, right: C, weight: Int) extends C case class C2(weight: Int) extends C
修改后,所有C的子类都必须提供weight字段,你可以直接在C类型实例上访问.weight而不会编译报错。
但你提到作业中不能修改类签名,这种情况下只能通过模式匹配的方式,在每个分支里访问对应子类的weight字段——模式匹配会让编译器识别当前分支的具体子类类型,从而允许访问该子类的专属字段。
内容的提问来源于stack exchange,提问作者figs_and_nuts
相关产品推荐
相关产品推荐

