Использование Java-обобщений в интерфейсе для обеспечения реализации метода с типом реализации в качестве параметра - PullRequest
3 голосов
/ 28 октября 2010

У меня есть такой интерфейс:

public interface DataObject {
    ...
    public void copyFrom(DataObject source);
    ...
}

И класс, который его реализует:

public class DataObjectImpl implements DataObject {
    ...
    @Override
    public void copyFrom(final DataObject source) {...}

    public void copyFrom(final DataObjectImpl source) {...}
    ...
}

Есть ли способ, которым я могу обеспечить реализацию "публичной пустоты"copyFrom (DataObjectImpl source) "метод в интерфейсе DataObject, используя обобщенные или иным образом?

Ответы [ 2 ]

4 голосов
/ 28 октября 2010

Если вам просто нужно обработать copyFrom по-другому, если заданное DataObject того же типа, что и сам объект, просто сделайте что-то вроде этого:

public class DataObjectImpl implements DataObject {
  public void copyFrom(final DataObject source) {
    if (source instanceof DataObjectImpl) {
      ...
    }
    else {
      ...
    }
  }
}

С другой стороны, вы может сделать это так, используя другое имя для метода, принимающего тип реализации.Тем не менее, я не понимаю, что хорошего это приносит.

public interface DataObject<T extends DataObject<T>> {
  public void copyFrom(DataObject source);
  public void copyFromImpl(T source);
}

public class DataObjectImpl implements DataObject<DataObjectImpl> {
  public void copyFrom(final DataObject source) { ... }
  public void copyFromImpl(final DataObjectImpl source) { ... }
}
3 голосов
/ 02 ноября 2010

Вы можете уменьшить свой код, просто выполнив:

interface DataObject {
   public <T> void copyFrom(T impl);
}

или чтобы быть более кратким:

interface DataObject {
   public <T extends DataObject> void copyFrom(T impl);
}

Вы можете использовать это, позвонив:

o.copyFrom(new DataObjectImpl());
o.<DataObjectImpl> copyFrom(new DataObjectImpl());

При использовании обобщений реализация DataObject всегда будет стираться во время выполнения.Кажется нелогичным знать о реализации, потому что вы должны программировать для интерфейса.На вашем месте я мог бы изучить объекты передачи данных или клонирование .

Как говорит Джош Блох, use interfaces only to define types.

Если ваштип был определен как:

interface DataObject {
   byte[] getData();
   Long getId();
   Timestamp getCreateDtTm();
}

Ваш импл может содержать:

class DataObjectImpl implements DataObject {
   // member vars
   public DataObjectImpl(DataObject dataObject) {
      this.data = dataObject.getData();
      this.id = dataObject.getId();
      this.createDtTm = dataObject.getCreateDtTm();
   }
   //getters and setters
}

Стратегия реализации или копирования не будет иметь значения, потому что любая реализация подчиняется контракту типа и может быть уменьшена доэто четко определенный тип.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...