@pqgg7nwkd4

Как сделать цепочки в наследующих классах java?

Добрый день.

Исходные данные: есть желание использовать Method chainig, т. к. это часто удобно.

Возьмем в пример: "животные".
Пусть есть родительский класс для всех животных, который поддерживает цепочки:
class Animal {
    public Animal setWeight(int newWeight) {
        return this;
    }
    public Animal setName(String newName){
        return this;
    }
}

// Как работает?
Animal animal = new Animal().setName("Murzik").setWeight(20);

// Удобно!


Всё красиво и просто. Теперь усложним задачу. Добавим кота:
class Cat extends Animal {
    public Cat setMeowVolume(int volume) {
        return this;
    }
}


Возникает проблема: методы setWeight и setName возвращают Animal и следующие конструкции работать не будут:
Cat cat1 = new Cat().setName("Murzik").setWeight(20).setMeowVolume(100); // Ошибка: setMeowVolume - не найден
Cat cat2 = new Cat().setMeowVolume(100).setName("Murzik").setWeight(20); // Ошибка: setWeight не возвращает Cat


Можно, конечно, применить кастинг. Но получается ужасно:
Cat cat1 = ((Cat)new Cat().setName("Murzik").setWeight(20)).setMeowVolume(100);
Cat cat2 = (Cat)new Cat().setMeowVolume(100).setName("Murzik").setWeight(20);


Можно наследовать все методы в Cat.
class Animal  {
    public Animal setWeight(int newWeight) {
        return this; 
    }
    public Animal setName(String newName){
        return this; 
    }
}

class Cat extends Animal {
    @Override
    public Cat setWeight (int newWeight) {
        super.setWeight(newWeight);
        return this;
    }

    @Override
    public Cat setName (String newName) {
        super.setName(newName);
        return this;
    }

    public Cat setMeowVolume(int volume) {
        return this;
    }
}

// Работает замечательно
Cat cat1 = new Cat().setName("Murzik").setWeight(20).setMeowVolume(100);
Cat cat2 = new Cat().setMeowVolume(100).setName("Murzik").setWeight(20);

// Проблемы:
// 1. Увеличение кода
// 2. Наследование методов там, где не оно не требуется.


Еще один способ. Он менее плох, но всё-же не так удобен как хотелось бы:
class Animal <Return extends Animal<Return>> {
    public Return setWeight(int newWeight) {
        return (Return)this; // Unchecked cast warning
    }
    public Return setName(String newName){
        return (Return)this; // Unchecked cast warning
    }
}
class Cat<Return extends Cat<Return>> extends Animal<Return> {
    public Return setMeowVolume(int volume) {
        return (Return)this; // Unchecked cast warning
    }
}

// Работает:
Cat cat1 = new Cat<>().setName("Murzik").setWeight(20).setMeowVolume(100);
Cat cat2 = new Cat<>().setMeowVolume(100).setName("Murzik").setWeight(20);

// Проблемы:
// 1. Куча предупреждений Unchecked cast.
// 2. Класс Cat становится generic-ом со всеми вытекающими последствиями и предупреждениями. (Например, конструктор необходимо указывать со скобками: new Cat<>()).
// 3. Грамозкое и малопонятное объявление классов.


Вот было бы здорово, если бы все void методы про вызове возвращали бы сам объект, или был бы возможен такой синтаксис:
class Animal  {
    public this setWeight(int newWeight) {

    }
    public this setName(String newName){

    }
}

class Cat extends Animal {
    this setMeowVolume(int volume) {
        
    }
}


Может быть я что-то упускаю?

Как бы вы организовали наследуемые классы с поддержкой chain вызовов?
  • Вопрос задан
  • 326 просмотров
Пригласить эксперта
Ответы на вопрос 3
@Free_ze
Пишу комментарии в комментарии, а не в ответы
Переопределяйте базовые методы.
Ответ написан
Комментировать
Чтобы избежать unchecked warning можно ещё вот так:
class Animal <Return extends Animal<Return>> {
    public Return setWeight(int newWeight) {
        return self();
    }
    public Return setName(String newName){
        return self();
    }
    @SuppressWarnings("unchecked")
    protected Return self() {
        return (Return) this;
    }
}
class Cat<Return extends Cat<Return>> extends Animal<Return> {
    public Return setMeowVolume(int volume) {
        return self();
    }
}
Ответ написан
Комментировать
jamakasi666
@jamakasi666 Куратор тега Java
Просто IT'шник.
Не сталкивался с подобными задачами как и никогда не использовал цепочки. Я конечно далекий от таких тонкостей и проблем как в вашем случае но может стоит попытаться написать серебряную пулю через аннотация\рефлексии?
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
Bell Integrator Ульяновск
До 400 000 ₽
Bell Integrator Хабаровск
До 400 000 ₽
Bell Integrator Ижевск
До 400 000 ₽
18 апр. 2024, в 01:12
150000 руб./за проект
18 апр. 2024, в 00:10
50000 руб./за проект