I have a class and two case subclasses:
abstract class C
case class C1(left: C, right: C, weight: Int) extends C
case class C2(weight: Int) extends C
I want to implement something like the following:
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
}
}
The above code does not compile. says left
and right
do not have attribute weight
. I am seeing this because C does not have a weight defined for it. Only c1
and c2
do. However, the class instances that I pass to the weight
function would be either c1
or c2
and would definitely have weight.
It is actually a recursive weight summation on a tree that I can achieve with the following:
def weight(t: C): Int = {
t match {
case c1: C1 => l.weight
case c2: C2 => weight(c2.left) + weight(c1.left)
}
}
But, I do not want to recurse and I do not think I should have to if the weight information is simply there available in the instance that I am passing in.
It is an assignment question that I am trying to solve and the signature of classes C
, C1
and C2
are sacrosanct. I have tried modifying
abstract class C
to
abstract class C:
val weight: Int = ???
However, this then starts raising issues with the weight
variable in the C1
and C2
signatures and asks me to override it.
The one solution I tried and thought would work was creating a companion object:
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
But I think the companion objects are not inherited by the subclasses
You should add member weight: Int
to 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
Then you can match typed patterns
def weight(t: C): Int =
t match
case c1: C1 => c1.left.weight + c1.right.weight
case c2: C2 => c2.weight
or constructor patterns
def weight(t: C): Int =
t match
case C1(l, r, _) => l.weight + r.weight
case C2(w) => w
Why do we have a need for separate case identifiers in case of type only matching in scala?
Normally abstract members are def
s and overriden with def
/val
/lazy val
(var
if necessary) in implementations.