How to get around the lack of abstract fields in J

2020-03-20 16:12发布

问题:

Assume, we have an abstract class A and we want to force all subclasses to have a certain field. This is not possible in Java, because we can not define abstract fields.

Workaround 1: Force subclasses to implement a method which delivers the wanted value.

abstract class A {
  abstract int getA();
}

Drawback: Each subclass has to implement a method for each abstract field we want to have. This can lead to many method implementations.

Advantage: We can use the method getA in the abstract class and implement methods with it in A without implementing them in each subclass. But the value behind the method can not be overwritten by the abstract class.

Workaround 2: Simulate the abstract field by forcing the subclass to give the abstract class a value.

abstract class A {
  int a;

  public A(int a) {
    this.a = a;
  }
}

Drawback: When we have multiple fields (> 10), the super constructor call will look a bit ugly and confusing.

Advantage: We can use the field a in the abstract class and implement methods with it in A without implementing them in each subclass. Plus, the value a can be overwritten by the abstract class.

Question: Which workaround is the common way to reach the goal ? Maybe there is a better one than the above ones ?

回答1:

The abstract method is probably the most object oriented.

If you have too many fields, you may want to regroup those in a POJO (if a new concept is appropriate).



回答2:

I prefer the first one . i dont love to couple classes in fileds name , how they handle state and how they save it. the first one is more close to open/close principal

I recommend to avoid inheritance. inheritance is very frigle and hard to maintenance. remember effective java advice - prefer composition other inheritance



回答3:

I think opt.1 is the cleaner by far. A few getters and setters is not a big deal, and I doubt that many use cases would have more than just a few abstract "fields".

About opt.2, you forget that constructors are not inherited, and thus would require all sub classes constructors to be implemented in a way that takes a into account.



回答4:

Workaround 2 is very common because of 2 advantages:

1) the one you mentioned - the field does not belong to the subclass - it belongs to the parent and that is important because it was "demanded" by the parent and because the parent can use it

2) When sub-classing from the parent you are very aware of this field because when you implement the constructor you must pass it on. If I saw the first workaround I wouldn't know what to understand from it, in this way I understand that the parent class needs this field to work, so it must have a meaningful value.

note: if you have a class that has 10 fields that need to be initialized something is probably wrong in your design.



回答5:

1. Actually its not about what one prefers but its about the flexibility, and the ability to adapt changes.

2. Its always better to Encapsulate Behaviors that keeps changing, either into an Interface or Abstract class.

3. You 1st Workaround will be good in places where you need different implementation for the same Behavior in Different classes. Then at this place either an Interface or your 1st Workaround will be a good choice.

Eg:

Consider Painting as a Class with paint() Method.

Now

paint() method can have Stroking, gliding, shading etc styles of doing it.

Then its better to Encapsulate that method into an Abstract class or an Interface.

public interface Paint{

paintDoIt(String style);

}

4. Your 2nd Wordaround will be good in a place, where you want certain behaviors to be MUST implemented by the Subclass.

Eg:

Consider Car as an Abstract Class, Now to be car its very important that it must have a Steering, 4 wheels, Engine, etc. So these features must be implemented.

where as other features like music system, LCD ,etc are optional and depends on the car type.