0

A subclass needs to define some property.

Can I write something like

abstract class AbstractSuperClass {
  protected Entity entity;
  protected abstract Action action; // all subclasses must define this on their own

  public AbstractSuperClass(Entity entity) {
    this.entity = entity;
  }

  public void operate() {
    this.action.doVoidMethod();
  }
}

public class SubClass extends AbstractSuperClass {
  public SubClass(Entity entity) {
    super(entity);
    this.action = new Action(); // I define the "abstract" property
    // now I expect SubClass.operate() to do this.action.doVoidMethod();
  }
}

Now, does calling new SubClass(entity).operate() do this.action.doVoidMethod() ?

My "problem" is that the AbstractSuperClass doesn't (it can't) define the property action, but subclasses must define it.

theonlygusti
  • 11,032
  • 11
  • 64
  • 119
  • Why don't you just try? – Federico klez Culloca Apr 06 '18 at 12:03
  • @FedericoklezCulloca compiling is expensive, and I want to learn about Java. I might learn something new and interesting by asking online. – theonlygusti Apr 06 '18 at 12:04
  • 1
    the code posted does not compile because the 'abstract' keyword is not allowed to be a modifier of the member field. Otherwise it is fine. My question is, what do you want to accomplish by making the Action member field 'abstract'? – bpgergo Apr 06 '18 at 12:09
  • @bpgergo the `AbstractSuperClass` doesn't define it, but subclasses _have_ to define it. It's a necessity. How can I necessitate this? – theonlygusti Apr 06 '18 at 12:11
  • Just put your `action` into `SubClass` and access it with getter and setter. If `AbstractSuperClass` don't need it, why are you declaring it there? – M_I Apr 06 '18 at 12:14

1 Answers1

0

There is no such thing as abstract field in Java (why?). If a base class wishes to have a field, it must declare it; all subclasses would inherit the field. If necessary, protected abstract methods could be declared for working with the field, requiring an override in each subclass:

abstract class MyBaseAbstract {
    protected abstract Action getAction();
    protected abstract void setAction(Action a);
}

class MyDerived extends MyBaseAbstract {
    private Action action;
    protected Action getAction() { return action; }
    protected void setAction(Action a) { action = a; }
}

This way each subclass would decide on how to store an Action field. It may decide not to store the field directly, providing a level of abstraction.

Initializing protected members the way you describe is fine. However, in situations when subclasses only assign a particular field in the constructor, but never access it directly after that, a better approach is to provide a protected constructor that takes the value of the field, and make the field private:

abstract class AbstractSuperClass {
    protected Entity entity;
    private Action action;

    protected AbstractSuperClass(Entity entity, Action action) {
        this.entity = entity;
        this.action = action;
    }

    public void operate() {
        this.action.doVoidMethod();
    }
}

public class SubClass extends AbstractSuperClass {
    public SubClass(Entity entity) {
        super(entity, new Action());
    }
}

does calling new SubClass(entity).operate() do this.action.doVoidMethod()

Now that abstract is removed from the field declaration, the code would compile and invoke doVoidMethod as expected.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523