In Scala I would write an abstract class with an abstract attribute path
:
abstract class Base {
val path: String
}
class Sub extends Base {
override val path = "/demo/"
}
Java doesn't know abstract attributes and I wonder what would be the best way to work around this limitation.
My ideas:
a) constructor parameter
abstract class Base {
protected String path;
protected Base(String path) {
this.path = path;
}
}
class Sub extends Base {
public Sub() {
super("/demo/");
}
}
b) abstract method
abstract class Base { // could be an interface too
abstract String getPath();
}
class Sub extends Base {
public String getPath() {
return "/demo/";
}
}
Which one do you like better? Other ideas?
I tend to use the constructor since the path value should not be computed at runtime.
A subclass must override all abstract methods of an abstract class. However, if the subclass is declared abstract, it's not mandatory to override abstract methods.
Java doesn't support abstract properties, if you try to mark a class property as abstract, you get a compilation error. In this tutorial, we introduce 2 ways for defining abstract properties which are set by subclasses without using the abstract keyword.
A non-abstract child class of an abstract parent class must override each of the abstract methods of its parent. A non-abstract child must override each abstract method inherited from its parent by defining a method with the same signature and same return type. Objects of the child class will include this method.
An abstract class can have a mixture of abstract and non-abstract methods. Subclasses of an abstract class must implement (override) all abstract methods of its abstract superclass. The non-abstract methods of the superclass are just inherited as they are. They can also be overridden, if needed.
What Scala does internally is what you are describing as method B.
Take the following example class:
abstract class Test{
val path: String
}
When you compile this with scalac, it will generate an abstract Java class with an abstract method named attr that returns a String. The reason this can happen is, because a val is constant and as such it can be emulated by only a getter and no setter. So if you want to access this class from Java, you can simply override the abstract getter method.
This is the equivalent of the Java class that will be produced (output of javap):
public abstract class Test extends java.lang.Object implements scala.ScalaObject{
public abstract java.lang.String path();
public Test();
}
If the path
never changes, I would go for option a, otherwise I would go for option b.
Another aspect is that the value of path
may not be available at the time of the construction. In that case option a is sort of ruled out. Comparing to your Scala code however, it seems like path
is available at the time of the construction.
The equivalent is B since the values is fixed.
Option A receives the path in the constructor, and that value could be computed during runtime which is not what the Sub
class in the scala example is goind.
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