Workaround for abstract attributes in Java

In Scala, I would write an abstract class with the abstract path attribute:

 abstract class Base { val path: String } class Sub extends Base { override val path = "/demo/" } 

Java does not know abstract attributes, and I wonder what would be the best way to get 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 do you like best? Other ideas?

I try to use the constructor as the path value should not be computed at runtime.

+6
java oop scala abstract-class attributes
source share
6 answers

What Scala does internally is what you describe as method B.

Take the following sample class:

 abstract class Test{ val path: String } 

When you compile this with scalac, it will generate an abstract Java class with an abstract method called attr, which returns String. The reason this can happen is because val is constant and as such it can only be emulated with a getter and without a setter. Therefore, 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 created (javap output):

 public abstract class Test extends java.lang.Object implements scala.ScalaObject{ public abstract java.lang.String path(); public Test(); } 
+5
source share

If path never changes, I would go for option a, otherwise I would go for option b.

Another aspect is that the path value may not be available at build time. In this case, variant a is as if excluded. Compared to your Scala code, it looks like path is available at build time.

+1
source share

Equivalent to B since the values ​​are fixed.

Option A gets the path in the constructor, and this value can be computed at runtime, which does not match the Sub class in the scala example.

+1
source share

You can try creating a protected method to set the value of a variable. Called only from classes in one package.

0
source share

I would choose option b, because if for some reason the path depends on other attributes, then it is not very nice to set the attribute in the superclass every time a different attribute changes. If you need to implement getter then no problem. I cannot come up with any specific case where option a would be more convenient.

0
source share

Or, probably, it’s good - the constructor parameter is probably easier if some calculation is never carried out (in this case you can make the field final, which will have an additional advantage to make sure that it is set by other constructors that can be added later) ; while the abstract method gives you more freedom to change things in the future.

You can also combine these two and set a private field in the constructor and provide a specific (but not final) implementation of the recipient who accesses it.

0
source share

All Articles