Я нашел проблему о статической привязке.Избегайте статической привязки в операциях, в которых используются аргументы иерархии
Мой настоящий класс очень расширен, поэтому я буду использовать несколько классов игрушек, чтобы выразить свою проблему.
Предположим, что у нас есть следующая иерархия.
public class Element{}
public class Element1 extends Element{}
public class Element2 extends Element{}
У меня есть класс, который Stock
использовать различные Element
специализацию, определяемую Element
иерархии.
public class Stock{
public void operation(Element1 e1){
System.out.println("Operation - " + e1.getClass().getName());
}
public void operation(Element2 e2){
System.out.println("Operation - " + e2.getClass().getName());
}
}
Наконец, у меня есть StockManager
, который позволяет управлять Stock
.
public StockManager{
Stock stock;
public StockManager(Stock stock){
this.stock=stock;
}
public void manage(List<Element> elements){
for(Element element: elements){
stock.operation(element);
}
}
}
Конечно, этот код не компилируется, потому что Stock
не определяет метод, который включает в себя Element
в качестве аргумента. В этом случае мы могли бы исправить код, используя разные подходы.
Во-первых, я смогу определить метод, который определит Element
как входной аргумент, например.
public void operation(Element e){
System.out.println("Operation - " + e.getClass().getName());
}
Этот метод может определить переключатель для управления различными бетонных элементов (Element1
, Element2
). Однако это невозможно для меня, потому что переключатель нарушает Open/Close Principle, и у меня много (много) конкретных элементов.
Другой вариант, я мог бы использовать что-то вроде Visitor Pattern. Я мог бы отправить объект Stock
на конкретный элемент. И конкретный элемент будет взимать плату за использование операций Stock
. Таким образом, класс может измениться на:
public abstract class Element{
public abstract void stockOperation(Stock stock);
}
public class Element1 extends Element{
public abstract void stockOperation(Stock stock){
stock.operation(this);
}
}
public class Element2 extends Element{
public abstract void stockOperation(Stock stock){
stock.operation(this);
}
}
И StockManager
.
public StockManager{
Stock stock;
public StockManager(Stock stock){
this.stock=stock;
}
public void manage(List<Element> elements){
for(Element element: elements){
element.stockOperation(stock);
}
}
}
Это позволяет определить, время компиляции статического типа конкретных элементов. И динамическая привязка будет взиматься за вызов метода нужного бетонного элемента stockOperation
(Element1
или Element2
). ОДНАКО !!, у меня есть дублирующий код в конкретных элементах, и у меня будет несколько конкретных элементов.
Итак, я хотел бы знать, знаем ли мы какой-либо шаблон или какую-либо передовую практику для решения этой проблемы. (Другой вариант, возможно, использовать отражение, но я бы не хотел его использовать).
абстрактные методы не могут содержать код внутри них. Вот почему они являются абстрактными «public abstract void stockOperation (Stock stock)) { stock.операция (это); } 'даже не компилируется –
Конечно, этот код не компилируется, потому что Stock не определяет метод, который включает в себя элемент как аргумент - почему, по вашему мнению, это не будет компилироваться? Вы передаете элемент, который расширяется как element1 & 2 – 6ton
@ 6ton. Потому что это перегрузка, а не полиморфизм. Когда происходит перегрузка, компилятор должен иметь возможность определять ** во время компиляции **, который вызывается перегруженным методом. И это не может. – ajb