Проблема при реализации абстрактного метода в 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);