I've recently created an immutable class supporting operations like +, -, etc. that returns a new instance of that class when it is changed.
I wanted to make a subclass of that class to add a bit of state and functionality but now I'm running into a problem in that all the original class's methods return instances of itself rather than the subclass.
Based on my current limited knowledge of Scala I can come up with this:
class Foo(val bar:Int) {
def copy(newBar:Int) = new Foo(newBar)
def + (other:Foo):This = copy(this.bar + other.bar)
}
class Subclass(barbar:Int) extends Foo(barbar) {
override def copy(newBar:Int) = new Subclass(newBar)
override def + (other:Subclass) = super.+(other).asInstanceOf[Subclass]
}
The problem here is quite obvious - all operations of the superclass that return a new instance of have to be re-defined in the subclass with a cast.
At first "this.type" seemed promising but "this.type" only includes "this" and not any other object of the same type.
Is there a standard pattern for making immutable classes easy to subclass? Something like:
class Foo(val bar:Int) {
def copy(newBar:Int):SameType = new Foo(newBar)
def + (other:Foo) = copy(this.bar + other.bar)
}
class Subclass(barbar:Int) extends Foo(barbar) {
override def copy(newBar:Int):SameType = new Subclass(newBar)
override def + (other:Subclass) = super.+(other).asInstanceOf[Subclass]
}
This particular approach would require the compiler to require that all subclasses implement a copy() method that returns the same type as that subclass, which would be perfectly fine with me. However, I don't think any such thing exists in Scala at this time.
Some work-arounds that come to mind are:
I'm sure this has been discussed many times already and I apologize for asking again. I did Google for a duplicate question without success, so my search terms must have been poorly constructed.
Thanks in advance,
Dobes
If you want to enforce immutability, you cannot have subclasses. See for example java. lang. String, which is a final class for this reason: To prevent people from subclassing String to make it mutable.
If the immutable class can be inherited, the subclass can change the methods to modify the instances of the class, so an immutable class cannot allow this.
Subclass. A class that inherits behaviors from another class, called superclass. In Scala, a class can only up have up to one superclass. Superclass. A class whose methods are inherited by one or more classes, called subclasses.
You could use an implementation trait, like the collection classes do, which is parametrized by the concrete type. E.g., something like:
trait FooLike[+A] {
protected def bar: Int
protected def copy(newBar: Int): A
def +(other: Foo): A = copy(bar + other.bar)
}
class Foo(val bar: Int) extends FooLike[Foo] {
protected def copy(newBar: Int): Foo = new Foo(newBar)
}
class Subclass(barbar: Int) extends Foo(barbar) with FooLike[Subclass] {
protected def copy(newBar: Int): Subclass = new Subclass(newBar)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With