праблема пры рэалізацыі абстрактнага метаду ў Java

Я хачу, каб змадэляваць такую ​​сітуацыю ў ААП:

enter image description here

Я хачу, каб клас Freight быць абстрактным класам, таму што я хацеў бы, каб мая праграма зараджае некаторыя дадатковыя зборы ў адпаведнасці са ступенню шкоднасці, што адна частка грузу мае.

На самай справе праблема, якую я атрымаў, што я хачу, каб клас Freight быць масівам аб'ектаў. Я маю на ўвазе, што ён можа захоўваць Кавалак багажных і Кавалачкі грузу. Маё пытанне, дзе я магу паставіць AddItem выкліку метаду? я павінен змясціць яго ў частку багажу і адзінкавых грузаў класаў? ці я павінен паставіць агульны абстрактны метад, званы AddItem у класе грузавых перавозак? нешта накшталт гэтага (я выкарыстоўваю 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 змяшчае масіў аб'ектаў тыпу багажу i грузу?

дзякуй

10
@SebastianRedl Разгледзім паддон асобных элементаў. Хоць я не спрачаюся ідэю Ор з'яўляецца добрым, грузы могуць быць аб'яднаны ў некалькі кропак у працэсе дастаўкі.
дададзена аўтар Dave Newton, крыніца
Гэта не мае сэнсу. Як частка грузу можа складацца з кавалкаў грузу? Вы блытае арыгінальны чысты дызайн. Калі вы жадаеце што-то, што з'яўляецца калекцыяй грузавых пунктаў, то мадэль, што ў якасці асобнага класа.
дададзена аўтар Sebastian Redl, крыніца

8 адказы

Я думаю, што ёсць недахоп дызайну тут, калі я разумею, гэта права. Вы павінны выкарыстоўваць аб'ект-кантэйнер, напрыклад Грузавыя , які ўтрымлівае Collection элементаў. Але калі прытрымлівацца гэтай канструкцыі тое, што вам трэба тут з'яўляецца Кампазітны я думаю.

Вытрымка з Вікіпедыі:

interface Freight{

    void addItem();
}

/** "Composite" */
class CompositePieceOfCargo implements Freight {

    private List childFreights = new ArrayList();

    public void addItem(Freight freight) {
        childFreights.add(freight);
    }

}

/** "Leaf" */
class PieceOfCargo implements Freight {
    private degreeHazard;

   //your methods here
}

Вы можаце выкарыстоўваць «Leaf» аб'ект у выпадку, калі вы маеце справу з бетонам Грузавыя і калі гэта проста «кантэйнер» вы можаце выкарыстоўваць «Кампазіт».

Гэты псеўда-код паказвае на недахоп дызайну: У аб'екце Leaf вы не можаце забяспечыць разумную рэалізацыю AddItem .

6
дададзена
дрэнна даць кропку, калі вы зробіце гэта адпавядае іерархіі класаў OP яшчэ.
дададзена аўтар Woot4Moo, крыніца
Добра я выправіў.
дададзена аўтар Adam Arold, крыніца

Калі вы хочаце Грузавыя , каб быць у стане трымаць гэтыя іншыя тыпы ў вас ёсць тры варыянты:

Хай кожны клас падоўжыць Грузавыя :

class Luggage extends Freight

АБО

даць Грузавыя масіў кожнага з іх:

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

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

АБО

зрабіць Камера і Cargo пашырыць базавы клас і пакласці, што ўнутры Грузавыя :

   class DeliveryItem  
   {  
        addItem(DeliveryItem item){...}  
   }  

class Luggage extends DeliveryItem  
{  
    //override addItem if need be
}    

class Freight
{  
     List items = new ArrayList();  

     List getItems()  
     {  
        return this.items;  
      }

     void addItem(DeliverItem item)  
     {
         this.items.add(item);
     }  
}  
5
дададзена
@ Woot4Moo чаму б не выкарыстоўваць інтэрфейс «DeliveryItem»?
дададзена аўтар Spring, крыніца
@Spring, таму што, хутчэй за ўсё, некаторыя функцыі па змаўчанні, якія могуць быць прадастаўлены. Гэта стандартная функцыя дадання са стандартнай рэалізацыяй, якія могуць быць перавызначаны, калі існуюць некаторую неабходнасць забеспячэння больш актыўная надбудовы.
дададзена аўтар Woot4Moo, крыніца
@jma абноўлены, каб паказаць, дзе AddItem можа пайсці
дададзена аўтар Woot4Moo, крыніца
@jma вы пытаецеся, як Грузавыя атрымлівае доступ да яго ўнутранаму набору DeliveryItem з?
дададзена аўтар Woot4Moo, крыніца
@jma абнаўляецца. Вы можаце проста напісаць аксессоров і мутаторов (геттеров/сетары), каб справіцца з гэтым тыпам дзейнасці.
дададзена аўтар Woot4Moo, крыніца
@jma ў дадзеным канкрэтным выпадку я хацеў бы пакінуць яго як абстрактныя, так як там не здаецца, любыя паводзіны па змаўчанні вы можаце паставіць.
дададзена аўтар Woot4Moo, крыніца
@ Woot4Moo, ды, як гэта можа паставіць элементы ў DeliveryItem і як атрымаць доступ да іх
дададзена аўтар Little, крыніца
дзякуй вам столькі @ Woot4Moo, апошняе пытанне пра закрыццё, як вы рэалізуеце AddItem у класе DeliveryItem, гэта абстрактны метад?
дададзена аўтар Little, крыніца
@ Woot4Moo і атрыбуты для грузавых аўтамабіляў, як ID і вага, павінны заставацца на Freight, ці яны павінны быць перамешчаныя ў DeliveryItem?. Я задаю гэтае пытанне, таму што цяпер багаж і грузы перанятыя ад DeliveryItem і не больш ад Грузавы
дададзена аўтар Little, крыніца
+1 за тое, што розныя варыянты.
дададзена аўтар christopher, крыніца

Ваш дызайн блытае «мае шмат» выгляду адносін з «з'яўляецца» сваім родам адносін.

PieceOfLugagge is not a Freight, sinces a Freight is composed from one or many pieces of lugagge.

Лепшы дызайн выглядае наступным чынам.

enter image description here

Калі вы думаеце пра яго, кавалкі lugagge таксама можа мець ступень шкоднасці, нават калі яна роўная нулю.

Freight has a collection of FreightItem, each FreightItem can be a PieceOfLugagge or a PieceOfCargo.

Freigth as an addItem() method ( not shown in drawing ) that accepts a FreightItem and adds it to the collection.

4
дададзена

Я маю на ўвазе, што ён можа захоўваць Кавалак багажных і Кавалачкі грузу.

Гэта гучыць жудасна шмат больш як Склад адносіны, чым ўспадкоўванне адносіны. Напрыклад, падумайце аб больш лагічнай суперкласса, як Кропка , і зрабіць Cargo і Камера падклас гэтага.

public abstract class Item  {}

public class Luggage extends Item {}

public class Cargo extends Item{}

Затым у Грузавыя клас, вам патрэбен масіў, і гэта можа быць тыпу Кропка .

public class Freight
{
    Item[] items;
}

Метад AddItem

Зараз гэта можа перайсці ў ПГК класа, улічваючы, што гэта той, які трымае ўсе вашы пытанні. Тады вы можаце рэалізаваць любыя абстрактныя метады ў вашай Кропка класа, і пераканайцеся, што ваш Камера і Cargo Клас рэалізацыі гэтых метадаў.

Ступень небяспекі

Скажам, кожны Кропка мае ступень шкоднасці. Што вы можаце зрабіць, гэта пакласці ступень значэнне ў вашым суперкласса, Кропка , напрыклад:

public abstract class Item {
    int hazard;

    public Item(int hazard)
    {
          //So hazard is in the superclass.
         this.hazard = hazard;
    }

    public int getHazard() { return hazard; }
}

Затым, у канструктару аднаго з вашых падкласаў, напрыклад Камеры , вы можаце мець:

public Luggage()
{
    super(5);
   //Example value.
   //Rest of constructor.
}
2
дададзена
чаму б не выкарыстоўваць інтэрфейс для класа Item?
дададзена аўтар Spring, крыніца
думаю, што маё рэдагаванне толькі высвеціла перавага выкарыстання абстрактнага класа.
дададзена аўтар christopher, крыніца

Разгледзім парушаючы ваш клас грузаў на два класа:

    <�Літый> а суперкласса, які ўяўляе сабой адзіны аб'ект Грузавыя (напрыклад, FreightItem). <�Літый> Калекцыя грузавых дэталяў (напрыклад, FreightGroup).

Увогуле, адзін эўрыстычны для аб'ектна-арыентаванага праектавання, каб зрабіць кожны клас ўяўляе роўна адну канцэпцыю.

2
дададзена
Actually the problem that I got is that I want that the Freight class to be an array of objects.

Я думаю, што ваша канцэпцыя блытае <�моцны> трымае фрахт і быўшы груз, што прыводзіць да вашай праблеме праектавання. Не ведаючы ўсю навакольнае асяроддзе, думаць аб гэтым праекце:

class FreightContainer: Holds your array (actually I would recommend a LinkedList or ArrayList, depending on the O(n) you want to have during runtime). Is responsible for adding (,publishing) and removing your Freight items, doing limit checks and so on. So this is where you would implement addItem(Freight newItem).

class Freight and subclasses: Are responsible for being the freight, thus having all attributes alike your UML above.

Там могуць быць далейшыя карэкціроўкі, але спатрэбіцца дадатковая інфармацыя аб вашай праблеме.

2
дададзена

Я думаю, вы павінны падзяліць ваш клас грузаў. Я буду рабіць нешта накшталт гэтага:

public interface Freight
public class Luggage extends Freight
public class Cargo extends Freight

public class FreightCollection
{
   private ArrayList freights;

   public FreightCollection(){
      freights = new ArrayList()
   }

   public void addFreight(Freight freight){
      freights.add(freight);
   }
}

Метад дапаўненні павінен належаць да калекцыі, а не да пункта яго аўтапартрэт.

2
дададзена

Як вы хочаце, каб ваш клас Freight правесці збор PieceOfLuggage і PieceOfCargo, я думаю, што вы хочаце, каб пашырыць клас, акрамя грузаў.

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);
1
дададзена