在Java中实现抽象方法时的问题

时间:2013-05-28 12:11:57

标签: java oop

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

enter image description here

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

实际上我遇到的问题是我希望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包含行李和货物类型的对象数组?

由于

8 个答案:

答案 0 :(得分:6)

如果我理解这一点,我认为这里存在设计缺陷。您应该使用像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
}

您可以使用“Leaf”对象,以防您处理具体的Freight,如果它只是一个“容器”,您可以使用“复合”。

此伪代码指出了设计缺陷:在Leaf对象中,您无法为addItem提供合理的实现。

答案 1 :(得分:5)

如果您希望Freight能够容纳其他类型,您有三种选择:

让每个班级都延伸Freight

class Luggage extends Freight

OR

Freight一个数组:

class Freight
{  
     Luggage[] luggage = new Luggage[10];  
     Cargo[] cargo = new Cargo[10];  

     addItem(Luggage luggage){...}  
     addItem(Cargo cargo){...}
}  

OR

make 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);
     }  
}  

答案 2 :(得分:4)

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

PieceOfLugagge不是Freight,因为Freight由一个或多个lugagge组成。

更好的设计如下。

enter image description here

当你想到它时,即使它是零,lugagge也可能具有危险程度。

Freight包含FreightItem个集合,每个FreightItem可以是PieceOfLugaggePieceOfCargo

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

答案 3 :(得分:2)

考虑将您的Freight类分为两类:

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

通常,面向对象设计的一种启发式方法是使每个类只代表一个概念。

答案 4 :(得分:2)

  

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

这听起来更像Composition关系,而不是inheritance关系。例如,考虑一个更合乎逻辑的超类,如Item,并使CargoLuggage成为其子类。

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.
}

答案 5 :(得分:2)

Actually the problem that I got is that I want that the Freight class to be an array of objects.

我认为您的概念混淆了持有运费和 运费,这导致您的设计问题。在不了解整个环境的情况下,请考虑一下这个设计:

类FreightContainer :保存您的数组(实际上我会推荐一个LinkedList或ArrayList,具体取决于您希望在运行时使用的O(n))。负责添加(,发布)和删除您的货运物品,进行限额检查等。所以这就是你要实现addItem(Freight newItem)的地方。

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

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

答案 6 :(得分: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方法必须属于一个集合,而不属于它自己的项目。

答案 7 :(得分: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);