10

我想在 OOP 中模拟以下情况:

在此处输入图像描述

我希望货运类是一个抽象类,因为我希望我的程序根据一件货物的危险程度收取一些额外的费用。

实际上,我遇到的问题是我希望 Freight 类是一个对象数组。我的意思是它可以存储一件行李和一件货物。我的问题是我可以在哪里放置一个方法调用 addItem?我应该把它放到 Puggage 和 Piece of Cargo 类中吗?还是应该将一个名为 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 包含一系列行李和货物类型的对象?

谢谢

4

8 回答 8

6

如果我理解这一点,我认为这里存在设计缺陷。您应该使用一个容器对象,例如Freight其中包含一个Collection项目。但是如果你坚持这个设计,我认为你需要的是一个复合材料

摘自维基百科:

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”对象,如果它只是一个“容器”,您可以使用“Composite”。

此伪代码指出了设计缺陷:在 Leaf 对象中,您无法为addItem.

于 2013-05-28T12:17:18.597 回答
5

如果您希望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){...}
}  

或者

创建LuggageCargo扩展一个基类并将其放入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);
     }  
}  
于 2013-05-28T12:15:36.390 回答
4

你的设计混淆了“有很多”的关系和“是”的关系。

PieceOfLugagge不是 a Freight,因为 aFreight是由一件或多件行李组成的。

一个更好的设计如下。

在此处输入图像描述

当你想到它时,行李件也可以具有危险度,即使它是零。

Freight有一个集合FreightItem,每个都FreightItem可以是 aPieceOfLugagge或 a PieceOfCargo

Freigth 作为 addItem() 方法(图中未显示),它接受 aFreightItem并将其添加到集合中。

于 2013-05-28T14:00:56.567 回答
2

考虑将您的货运类分为两个类:

  • 表示单个 Freight 对象的超类(例如,FreightItem)。
  • 货运项目的集合(例如,FreightGroup)。

一般而言,面向对象设计的一个启发式方法是让每个类准确地表示一个概念。

于 2013-05-28T12:16:14.060 回答
2

我的意思是它可以存储一件行李和一件货物。

这听起来更像是一种Composition关系,而不是一种inheritance关系。例如,考虑一个更合乎逻辑的超类,比如Item, 和 makeCargo以及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类中实现任何抽象方法,并确保你LuggageCargo类实现这些方法。

危险程度

比方说,每个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.
}
于 2013-05-28T12:17:45.463 回答
2
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) 的地方。

类运费和子类:负责作为运费,因此具有与您上面的 UML 类似的所有属性。

可能会有进一步的调整,但这需要关于您的问题的更多信息。

于 2013-05-28T12:27:21.423 回答
2

我认为您应该拆分货运班。我会做这样的事情:

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 方法必须属于一个集合,而不是项目本身。

于 2013-05-28T12:29:36.800 回答
1

由于您希望 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);
于 2013-05-28T13:04:36.643 回答