Передача настроек через интерфейсы в Java - возможно? - PullRequest
1 голос
/ 23 марта 2019

Давайте предположим, что у меня есть два класса.

public class Banana extends Fruit{    
    public Banana() {
        this.setTitle("Banana");
        this.setSize("Medium");
        this.setState("Rotten");
    }
}
public class Sausage extends Meat{    
    public Sausage() {
        this.setTitle("Sausage");
        this.setSize("Medium");
        this.setState("Rotten");
    }
}

Есть ли способ представить интерфейс (возможно, с методами по умолчанию), который бы содержал общие настройки?Оба оригинальных расширения должны остаться.

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

Ответы [ 4 ]

1 голос
/ 23 марта 2019

Вы не можете сделать это напрямую. Я думаю, что то, о чем вы здесь в основном просите, это множественное наследование, и эта концепция, кажется, дает разработчикам языка Java плохую опрометчивость. Вы можете реализовать что-то подобное самостоятельно.

Предположим, у вас есть интерфейс Food

public interface Food {    
    void setTitle(String s);
    void setSize(String s);
    void setState(String s);
}

Тогда вы можете сделать это:

public class BaseFood implements Food {  
    private String title;  
    private String size;  
    private String state;  
    // setters and getters...
}

А потом вот это:

public class Banana extends Fruit implements Food {    
    private BaseFood food = new Food();
    public Banana() {
        food.setTitle("Banana");
        food.setSize("Medium");
        food.setState("Rotten");
    }
}

Для полноты, вот Sausage, это в основном то же самое, что и Banana:

public class Sausage extends Meat implements Food {    
    private BaseFood food = new Food();
    public Sausage() {
        food.setTitle("Kielbasa");
        food.setSize("Medium");
        food.setState("Tasty");
    }
}

Это называется «делегированием», когда вы делегируете реализацию какого-либо интерфейса в Java другому объекту, только заявляя, что он реализует общий интерфейс, а затем просто вызывая методы для частного экземпляра, который фактически реализует этот интерфейс. Это в основном ручное множественное наследование.

Достаточно часто, что моя IDE (NetBeans) сделает большую часть работы за меня. При наличии интерфейса и члена частного экземпляра, который реализует этот интерфейс, он напишет все методы, необходимые для публичной реализации этого интерфейса. Это работает хорошо, но может генерировать много шаблонного. Я бы хотел, чтобы люди на Java хотя бы частично нашли решение в языке «проблемы множественного наследования».

РЕДАКТИРОВАТЬ: Вы сказали, что нет общих классов, но затем вы сказали это:

Вы не можете создать базовый класс в этом случае, так как это Java с единым наследованием - и Sausage, и Banana уже что-то расширяют. Если я не пропущу что-то, что вы можете увидеть ...

Если вы можете изменить наследование, вы можете создать общий базовый класс:

class Food { ...
class Fruit extends Food {...
class Banana extends Fruit {...
class Meat extends Food {...
class Sausage extends Meat { ...

Но мой ответ предполагал, что вы не можете сделать это по любой причине.

0 голосов
/ 23 марта 2019

Интерфейсы только определяют контракт, который должны выполнять реализации, но обычно не раскрывают никаких деталей реализации.(без учета методов по умолчанию здесь)

То, что вы имеете в виду, это, вероятно, класс abstract или общий суперкласс, который наследует эти общие свойства подклассам.Эти классы могут содержать конкретное состояние.

/**
 * The contract for each food.
 * You can get its title, size and its state. Also, the state can be changed.
 */
public interface Food {
    String getTitle();
    String getSize();
    String getState();
    void setState(String state);
}

Теперь класс abstract может определять общее поведение:

public class AbstractFood implements Food {

    private String title;
    private String size;
    private String state;

    public AbstractFood(String title, String size, String state) {
        this.title = title;
        this.size = size;
        this.state = state;
    }

    @Override
    public String getTitle() {
        return null;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    @Override
    public String getSize() {
        return null;
    }

    public void setSize(String size) {
        this.size = size;
    }

    @Override
    public String getState() {
        return null;
    }

    @Override
    public void setState(String state) {
        this.state = state;
    }
}

И эти классы могут иметь произвольные подклассы, например, Fruit.

public class Fruit extends AbstractFood {

    public Fruit(String title, String size, String state) {
        super(title, size, state);
    }
}

Определите класс Banana, который является Fruit:

public class Banana extends Fruit {

    public Banana(String size, String state) {
        super("Banana", size, state);
    }
}

Возвращаясь к пользователю интерфейса Food, вы можете теперьприменять общее поведение ко всем типам пищи, не зная каких-либо деталей реализации.Например, вы можете изменить состояние всех бананов на гнилые:

for (Fruit fruit : fruits) {
    if (fruit.getTitle().equals("Banana")) {
        fruit.setState("Rotten");
    }
}
0 голосов
/ 23 марта 2019

Интерфейсы используются для определения некоторых общих поведения .Если вам нужно общее состояние , вам следует использовать базовый класс, который можно сделать также абстрактным, если он не будет создан непосредственно.

0 голосов
/ 23 марта 2019

Вопрос в том, какие свойства вы хотите сохранить?

Вы можете объявить открытые статические конечные поля в интерфейсах, как в любом классе:

public interface MyInterface {
    String PROPERTY = "MyProperty";
}

Если этого недостаточно, вам, вероятно, придется использовать наследование вместо интерфейса и хранить общие свойства там, в абстрактном объекте.

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