Проблема при реализации абстрактного метода в Java
Я хочу моделировать следующую ситуацию в ООП:
![enter image description here]()
Я хочу, чтобы класс фрахта был абстрактным классом, потому что я хотел бы, чтобы моя программа взимала некоторые дополнительные сборы в соответствии со степенью опасности, что одна часть груза имела.
Фактически проблема, которую я получил, это то, что я хочу, чтобы класс Freight был массивом объектов. Я имею в виду, что он может хранить кусок багажа и куски груза. Мой вопрос: где я могу поместить вызов метода addItem? должен ли я поместить его в классы "Часть багажа" и "Класс груза"? или я должен поместить общий абстрактный метод addItem в класс Freight? что-то вроде этого (я использую Java для этой цели):
abstract class Freight{
//other things here
protected Freight[] fr=Freight[10];
protected int numItems;
abstract addItem();
}
class PieceOfLuggage extends Freight{
//other things
public PieceOfLuggage(int iden,double weight,int id){
super(iden,weight,id)
}
public addItem(){
fr[numItems]=this;
numItems++;
}
}
class PieceOfCargo extends Freight{
private degreeHazard;
public PieceOfCargo(int iden,double weight,int id,int degHazard){
super(iden,weight,id);
degreeHazard=degHazard;
}
public addItem(){
fr[numItems]=this;
numItems++;
}
}
так что в моей основной программе я могу сделать что-то вроде:
Luggage l1=new Luggage(100,50,1234); //ident, weight, id
Cargo c1=new Cargo(300,123.56,1111,1); //ident, weight, id, degree of hazard
l1.addItem();
c1.addItem();
любое предложение, где я могу поместить этот метод addItem?, так что класс Freight содержит массив объектов типа багажа и груза?
Спасибо
Ответы
Ответ 1
Если вы хотите, чтобы Freight
мог удерживать эти другие типы, у вас есть три варианта:
Сделайте каждый класс расширенным Freight
:
class Luggage extends Freight
ИЛИ
укажите Freight
массив каждого из них:
class Freight
{
Luggage[] luggage = new Luggage[10];
Cargo[] cargo = new Cargo[10];
addItem(Luggage luggage){...}
addItem(Cargo cargo){...}
}
ИЛИ
сделать Luggage
и Cargo
расширить базовый класс и поместить его внутри Freight
:
class DeliveryItem
{
addItem(DeliveryItem item){...}
}
class Luggage extends DeliveryItem
{
//override addItem if need be
}
class Freight
{
List<DeliveryItem> items = new ArrayList<DeliveryItem>();
List<DeliveryItem> getItems()
{
return this.items;
}
void addItem(DeliverItem item)
{
this.items.add(item);
}
}
Ответ 2
Я думаю, что здесь есть недостаток дизайна, если я понимаю это право. Вы должны использовать объект-контейнер, например Freight
, который содержит Collection
элементов. Но если вы придерживаетесь этого дизайна, то вам понадобится Composite.
Выдержка из википедии:
interface Freight{
void addItem();
}
/** "Composite" */
class CompositePieceOfCargo implements Freight {
private List<Freight> childFreights = new ArrayList<Freight>();
public void addItem(Freight freight) {
childFreights.add(freight);
}
}
/** "Leaf" */
class PieceOfCargo implements Freight {
private degreeHazard;
// your methods here
}
Вы можете использовать объект "Лист", если вы имеете дело с конкретным Freight
, и если это просто "контейнер", вы можете использовать "Композит".
Этот псевдо-код указывает на дефект дизайна: в объекте Leaf вы не можете обеспечить разумную реализацию для addItem
.
Ответ 3
Ваш дизайн смущает "имеет много" вид отношений с "является" видом отношений.
PieceOfLugagge
не является Freight
, sinces a Freight
состоит из одной или нескольких частей lugagge.
Лучший дизайн выглядит следующим образом.
![enter image description here]()
Когда вы думаете об этом, куски lugagge также могут иметь степень опасности, даже если он равен нулю.
Freight
имеет набор FreightItem
, каждый FreightItem
может быть PieceOfLugagge
или PieceOfCargo
.
Freigth как метод addItem() (не показан на чертеже), который принимает FreightItem
и добавляет его в коллекцию.
Ответ 4
Подумайте о том, чтобы разбить свой класс фрахта на два класса:
- Суперкласс, представляющий один объект Freight (например, FreightItem).
- Коллекция элементов фрахта (например, FreightGroup).
В общем, одна эвристика для объектно-ориентированного дизайна заключается в том, чтобы каждый класс представлял ровно одно понятие.
Ответ 5
Я имею в виду, что он может хранить кусок багажа и куски груза.
Это звучит намного больше, чем отношение Composition
, чем отношение inheritance
. Например, подумайте о более логичном суперклассе, например Item
, и сделайте Cargo
и Luggage
подкласс этого.
public abstract class Item {}
public class Luggage extends Item {}
public class Cargo extends Item{}
Тогда в вашем классе Freight
вам понадобится массив, и это может быть типа Item
.
public class Freight
{
Item[] items;
}
Метод addItem
Теперь это можно использовать в классе Freight
, учитывая, что это тот, который держит все ваши элементы. Затем вы можете реализовать любые абстрактные методы в своем классе Item
и убедиться, что ваши методы Luggage
и Cargo
реализуют эти методы.
Степень опасности
Скажем, каждый Item
имеет степень опасности. То, что вы МОЖЕТЕ сделать, помещает значение degree
в ваш суперкласс, Item
, например:
public abstract class Item {
int hazard;
public Item(int hazard)
{
// So hazard is in the superclass.
this.hazard = hazard;
}
public int getHazard() { return hazard; }
}
Затем в конструкторе одного из ваших подклассов, например Luggage
, вы можете:
public Luggage()
{
super(5);
// Example value.
// Rest of constructor.
}
Ответ 6
Actually the problem that I got is that I want that the Freight class to be an array of objects.
Я думаю, что ваша концепция смешивает размещение фрахта и фрахта, что приводит к вашей проблеме с дизайном. Не зная всей окружающей среды, подумайте об этом дизайне:
class FreightContainer: удерживает ваш массив (на самом деле я бы рекомендовал LinkedList или ArrayList в зависимости от O (n), который вы хотите иметь во время выполнения). Отвечает за добавление (публикацию) и удаление ваших товаров, выполнение лимитов и т.д. Таким образом, здесь вы должны реализовать addItem (Freight newItem).
Класс Freight и подклассы: ответственны за фрахт, таким образом, все атрибуты похожи на ваш UML выше.
Там могут быть дополнительные корректировки, но для этого потребуется дополнительная информация о вашей проблеме.
Ответ 7
Я думаю, вы должны разделить свой класс фрахта. Я сделаю что-то вроде этого:
public interface Freight
public class Luggage extends Freight
public class Cargo extends Freight
public class FreightCollection
{
private ArrayList<Freight> freights;
public FreightCollection(){
freights = new ArrayList<Freight>()
}
public void addFreight(Freight freight){
freights.add(freight);
}
}
Метод add должен принадлежать коллекции, а не к элементу it-self.
Ответ 8
Как вы хотите, чтобы ваш класс Freight собрал коллекцию PieceOfLuggage и PieceOfCargo, я думаю, вы хотите, чтобы они расширили класс, отличный от Freight.
class Freight{
protected FreightPiece[] fr=FreightPiece[10];
protected int numItems;
public addItem(FreightPiece piece)
{
// add the piece to fr
}
}
abstract class FreightPiece {
}
class PieceOfLuggage extends FreightPiece{
public PieceOfLuggage(int iden,double weight,int id){
super(iden,weight,id)
}
}
class PieceOfCargo extends FreightPiece{
private degreeHazard;
public PieceOfCargo(int iden,double weight,int id,int degHazard){
super(iden,weight,id);
degreeHazard=degHazard;
}
}
Итак, тогда
Freight fr = new Freight();
PieceOfLuggage l1=new PieceOfLuggage(100,50,1234); //ident, weight, id
PieceOfCargo c1=new PieceOfCargo(300,123.56,1111,1); //ident, weight, id, degree of hazard
fr.addItem(l1);
fr.addItem(c1);