mardi 12 juillet 2022

Should developers add new methods in abstract implementations of interfaces?

Today, I noticed something about my OOP style.

Say I have an interface:

public interface Property<T> {

  String getName();

  String getValue(T target);

  void setValue(T target, String value);
}

I may create an abstract class:

public abstract class AbstractProperty<T> implements Property<T> {

  protected(final String name) {
    if(name == null) throw new IllegalArgumentException();

    this.name = name;
  }

  protected abstract T getValueSafe(T target);

  protected abstract T setValueSafe(T target, String value);

  private final String name;

  @Override
  public String getName() {
    return name;
  }

  @Override
  public String getValue(final T target) {
    if(target == null) throw new IllegalArgumentException();

    return getValueSafe(target);
  }

  @Override
  public void setValue(final T target, final String value) {
    if(target == null) throw new IllegalArgumentException();

    return setValueSafe(target, value);
  }

}

My question is, was it poor design to implement getValue and setValue in an abstract class implemented an interface, especially considering they are not field accessors?

From a OOP-in-Java perspective, would it make more sense to have an abstract class implementing only field accessors,

public abstract class AbstractProperty<T> implements Property<T> {

  protected(final String name) {
    if(name == null) throw new IllegalArgumentException();

    this.name = name;
  }

  private final String name;

  @Override
  public String getName() {
    return name;
  }

}

and another abstract class with added functionality:

public abstract class SimpleProperty<T> extends AbstractProperty<T> {

  protected(final String name) {
    super(name)
  }

  protected abstract T getValueSafe(T target);

  protected abstract T setValueSafe(T target, String value);

  @Override
  public String getValue(final T target) {
    if(target == null) throw new IllegalArgumentException();

    return getValueSafe(target);
  }

  @Override
  public void setValue(final T target, final String value) {
    if(target == null) throw new IllegalArgumentException();

    return setValueSafe(target, value);
  }

}

I can envision how the latter could offer more extensibility, but would love to hear thoughts from those more experiences.

Aucun commentaire:

Enregistrer un commentaire