Тот же метод для нескольких классов, реализующих один и тот же интерфейс

Извините, я действительно не знал, как назвать вопрос, вот проблема...

У меня есть интерфейс и несколько классов, которые реализуют интерфейс. Реализация некоторых из методов в интерфейсе в каждом классе реализации одинакова. Я чувствую, что должен быть способ упростить это, поэтому мне не нужно писать один и тот же код каждый раз. Пример:

public interface Foo {
    String getName();
}

public class FooImpl1 implements Foo {
    private String name = "foo name1";

    public String getName() {
        return name;
    }
}

public class FooImpl2 implements Foo {
    private String name = "foo name2";

    public String getName() {
        return name;
    }
}

Итак, чтобы сломаться..

  • Есть ли способ поместить код для getName в одном месте, и каждый класс имеет собственную переменную имени?

  • Есть ли способ сделать getName static, поэтому мне не нужно создавать новый экземпляр

Иметь лучшие идеи?

Ответ 1

Используйте абстрактный класс и инициализируйте поле в конструкторе:

public abstract class Foo {

 protected String name;

 String getName() {
  return name;
 }
}

public class FooImpl1 extends Foo {

 public FooImpl1 () {
  name = "foo name1";
 }
}

public class FooImpl2 extends Foo {

 public FooImpl1 () {
  name = "foo name2";
 }
}

JB Nizlet указал, что было бы более чистым сделать что-то вроде этого:

public abstract class Foo {

protected String name;

public Foo(String newName) {
    name = newName;
}

 String getName() {
  return name;
 }
}

И затем вызовите super("foo name 1") в подклассы.

Как @Peter Lawrey сказал, что если у вас уже есть интерфейс или вы хотите по какой-то другой причине:

public interface IFoo {
 String getName();
}

public abstract class Foo implements IFoo {

 protected String name;

 String getName() {
  return name;
 }
}

Ответ 2

Вы можете сделать очень простой подход:

public interface Foo {

    String getName();
}

public class Named implements Foo {

    String name;

    public String getName() {
        return name;
    }
}

public class FooImpl1 extends Named {
    {name = "foo name1";}
}

public class FooImpl2 extends Named {
    {name = "foo name2";}
}

Ответ 3

Это не работает для геттеров, как в вашем примере, но поскольку вопрос более общий, я думаю, стоит упомянуть, что с Java 8 вы можете определить методы по умолчанию в интерфейсах. Итак, если у вас было что-то более сложное, например:

public interface ComplexFoo {
    String getFirstName();
    String getLastName();

    String getFullName();
}

Вам не нужно повторять реализацию getFullName в каждом подклассе, но можете указать его в интерфейсе:

public interface ComplexFoo {
    String getFirstName();
    String getLastName();

    default String getFullName() {
        return getFirstName() + " " + getLastName();
    }
}

Геттеры, хотя все еще нуждаются в повторении, поскольку они получают доступ к элементам, которые еще не доступны в интерфейсе:

public class FooImpl1 implements ComplexFoo {
    private String firstName = "foo";
    private String lastName = "name1;

    private String getFirstName() { return firstName; }
    private String getLastName() { return lastName; }
}

public class FooImpl2 implements ComplexFoo {
    private String firstName = "foo";
    private String lastName = "name2;

    private String getFirstName() { return firstName; }
    private String getLastName() { return lastName; }
}