WebHU - Programozási kérdések és válaszok

Összehasonlító készítése két szuperre kiterjedő osztályhoz

Elnézést kérek a generikus gyógyszerekkel kapcsolatos korlátozott ismereteimért.

A következő helyzetem van:

1. osztály:

public class PostProcess implements Serializable {
    public int          order;
    // Several other variables.

    // Constructor setting vars
    public PostProcess(){

    }

    /* Getters and setters for variables */
}

2. osztály:

public class Application extends PostProcess{
    public int      subOrder;
    // Several other variables.

    // Constructor setting vars
    public Application(){

    }

    /* Getters and setters for variables */

}

3. osztály:

public class FileOperation extends PostProcess{
    public int      subOrder;
    // Several other variables (different from class 'Application').

    // Constructor setting vars
    public FileOperation(){

    }

    /* Getters and setters for variables */

}

Amit egy másik osztályban próbálok elérni, az az, hogy rendezek egy listát, amely a következőképpen definiált "FileOperation" és "Application" objektumok keverékét tartalmazza:

private ArrayList<? extends PostProcess> processList = new ArrayList<PostProcess>();

Ennek a rendezésnek mindkét objektum két mezőjében kell lennie, nevezetesen: 'order' és 'subOrder'. Az „order” a PostProcess-ből öröklődött, az „alrend” pedig az „Application” és a „FileOperation” osztályban is definiálva van.

A Generics, Comparable, Comparators és Interfaces témájú utam során úgy gondolom, hogy összekevertem a dolgokat.

Megpróbálok egy rendezést alkalmazni a következő használatával:

Collections.sort(processList, new PostProcessComparator());

A PostProcessComparator meghatározása a következő:

public class PostProcessComparator implements Comparator<? extends PostProcess> {

    @Override
    public int compare(Object p1, Object p2) {

      int mainOrderCompare = p1.getOrder().compareTo(p2.getOrder());
      if (mainOrderCompare != 0) {
        return mainOrderCompare;
      } else {
        return p1.getSubOrder().compareTo(p2.getSubOrder());
      }
    }
}

Kérdések:

Tudom, hogy a Comparatorom (és talán több is) hibás, de nem tudom, pontosan hol. Azért vagyok itt, hogy tanuljak ;)

  1. Észrevettem, hogy a 'processList' List meghatározása nem a megfelelő módszer. Amikor megpróbálok hozzáadni egy 'FileOperation' vagy 'Application' objektumot a listához, a fordító a szemembe vág, hogy "nincs megfelelő metódus az add(Application)"-hez (ugyanez a FileOperation esetében is). Helytelenül feltételeztem, hogy használhatok általánosakat a processList típusaim deklarálásához? helyesnek kell lennie, mivel mindkét osztálynak a PostProcess a szuperosztálya, igaz?
  2. A PostProcessComparator osztályhatárokkal való definiálása működnie kell a szememben, mivel csak azokat az objektumokat szeretném összehasonlítani, amelyeknek a PostProcess szuperosztálya van (és így ugyanazokhoz a metódusokhoz férnek hozzá).
  3. Hogyan érhetem el az argumentált objektumokat a Comparator osztályban p1 és p2 esetén (mert a típusukat továbbra is deklarálnom kell az argumentumokhoz:

    @Override
    public int compare(<What to put here?> p1, <And here?> p2) {
    
    }
    

Nagyon remélem, hogy tudtok segíteni! Ha valamiben nem lennék világos, szóljon, és rosszul részletezze.

Kösz!

SZERKESZTÉS

NickJ-nek és Winzunak köszönhetően elvégeztem a szükséges változtatásokat a komparátorban és az ArrayList definícióban.

  • Áthelyeztem az Alrendet az Application and FileOperationből a szülőosztályba (és védetté tettem őket)
  • A komparátor újradefiniált paraméterezése:

    public class PostProcessComparator<T extends PostProcess> implements Comparator<T> 
    
  • Az Integer.compare(p1.getOrder(), p2.getOrder())-t használta a kezdeti összehasonlító összehasonlításhoz.

Most az utolsó kihívás (fordítói figyelmeztetések) Híváskor:

    Collections.sort(processList, new PostProcessComparator());

Figyelmeztetést kapok: - [nincs bejelölve] nincs bejelölve metódushívás: a Collections osztályban a metódusrendezés az adott típusokra vonatkozik

    required:  List<T>,Comparator<? super T>
    found: ArrayList<PostProcess>,PostProcessComparator

A paraméterezés az én szememben megfelelő ehhez a komparátorhoz, eltekintve attól, hogy nem ellenőriztem az objektumtípusokat.

Hol lehet ez rosszul?


  • Tervezési kérdés - miért nem teszed be a SubOrder tulajdonságot a PostProcess osztályba, és például védetté teszed, így a származtatott osztályok használhatják? 16.10.2013
  • @AlexAdas Ez jó ötlet. ezen nem gondolkodtam. Hadd próbáljam ki! Köszönöm 16.10.2013
  • Frissítettem a válaszomat az utolsó aggodalmára 16.10.2013
  • Nagyon köszönöm Winzu. Tökéletesen működött. Most nehéz kiválasztani a helyes választ, mivel két részből állt. +2 neked. Nagyon köszönöm a segítséget. 16.10.2013

Válaszok:


1

Az egyetlen probléma, amit találtam, az volt, hogy a PostProcessComparatort így kell paraméterezni:

public class PostProcessComparator<T extends PostProcess> implements Comparator<T> {

  @Override
  public int compare(T p1, T p2) {

    int mainOrderCompare = p1.getOrder().compareTo(p2.getOrder());
    if (mainOrderCompare != 0) {
      return mainOrderCompare;
    } else {
      return p1.getSubOrder().compareTo(p2.getSubOrder());
    }
  }
}

Most az összehasonlítás() metódus elfogadja a megfelelő osztályt (kibővíti a PostProcess-t), így a PostProcess bármely nyilvános metódusa meghívható a comlpare()-ből.

Végül, a mezők nem lehetnek nyilvánosak. Javaslom a mezők védetté tételét, így az alosztályok továbbra is örökölhetik őket, de a beágyazás megmarad.

16.10.2013
  • Az int primitív típusnál nem használhatja az összehasonlítást. Használja a - operátort vagy az Integer.compare(p1.getOrder(), p2.getOrder()); 16.10.2013
  • Jó megállapítás! Most másoltam az eredeti kódot, megváltoztattam az általános paraméterezést. 16.10.2013
  • @NickJ Nagyon köszönöm, úgy tűnik, valóban működik. Egy másik fordítói hiba azonban azt jelzi, hogy a p1 és p2 objektumaim nem rendelkeznek a getSubOrder() metódussal (nem található szimbólum). Mi lehet a helyes, mert úgy állítottam, hogy a listám csak a ‹PostProcess› típusokat tartalmazza, a gyermekeit nem? A p1 (T típusú) és p2 objektumok nem férnek hozzá a getSubOrder() metódushoz? 16.10.2013
  • Nem – mivel a T kiterjeszti a PostProcess-t, a komparátor csak a PostProcess-ben definiált metódusokról tud, annak alosztályairól nem. Ha alosztály metódusokat kell meghívnia, vagy használjon külön Comparators-t, minden egyes alosztályhoz egyet, vagy ellenőrizze a tényleges osztályt az instanceof segítségével, és leadja őket. 16.10.2013

  • 2

    NickJ fenti válasza megmutatja, hogyan kell megvalósítani a komparátort.

    Abban, amit csinálsz, te is szeretnél változtatni

    private ArrayList<? extends PostProcess> processList = new ArrayList<PostProcess>();.
    

    to

    ArrayList<PostProcess> processList = new ArrayList<PostProcess>();
    

    Ez az oka annak, hogy nem adhatja hozzá az Application et FileOperation objektumokat a listához.

    Ez egy kicsit trükkös. Talán ez a bejegyzés segít megérteni

    A Java listákkal és interfészekkel ellátott általánosokat használ

    Az Alrendet is szeretné a szülőosztályban.

    import java.io.Serializable;
    
    public class PostProcess implements Serializable {
    private int          order;
    private int      subOrder;
    // Several other variables.
    
    public int getSubOrder() {
        return subOrder;
    }
    
    public void setSubOrder(int subOrder) {
        this.subOrder = subOrder;
    }
    
    public int getOrder() {
        return order;
    }
    
    public void setOrder(int order) {
        this.order = order;
    }
    
    // Constructor setting vars
    public PostProcess(){
    
    }
    
    }
    

    Végül hívja meg a komparátort így, hogy elkerülje a bejelöletlen figyelmeztetést:

     Collections.sort(processList, new PostProcessComparator<PostProcess>());
    
    16.10.2013
  • Köszönöm Winzu! Ez megtette a trükköt (a fordító számára), de a definiált p1 és p2 objektumok (T típusú) a komparátorban most nem férnek hozzá (nem található szimbólum) a getSubOrder metódushoz. Ez azért van, mert az ArrayList‹PostProcess› korlátozza az elérhető metódusokat? 16.10.2013
  • Mivel mindkét Application és FileOperation objektumnak van SubOrder, nem látom okát, hogy az SubOrder ne a PostProcess osztályban legyen. Hadd módosítsam a választ. 16.10.2013
  • Köszönöm. A szerkesztést a jelenlegi megoldásokkal és az utolsó megjelenő fordítói figyelmeztetéssel végeztem el. 16.10.2013

  • 3

    Csak módosítsd a következőre:

    public class PostProcessComparator implements Comparator<PostProcess> {
        @Override
        public int compare(PostProcess p1, PostProcess p2) {
          //...
        }
    }
    

    Ez az. Van egy összehasonlító, amely képes összehasonlítani a PostProcess bármely két példányát (és a PostProcess alosztályainak példányai a PostProcess példányai).

    17.10.2013
  • Kezdetben hozzáadtam a 'subOrder' mezőt az alárendelt 'FileOperation' és 'Application'-hez. Ha az átadott objektumokat a 'PostProcess'-be öntjük, nem férek hozzá ezekhez a hozzáférési metódusokhoz, mert a 'PostProcess' nem örökölte őket, igaz? A tervem revíziója (alOrder áthelyezése a PostProcess szülőosztályba) megoldást jelentene. De ha jól értem nem működött volna a megoldásod, amikor az alOrder csak a gyerekek része volt? Vagy itt tévedek? 17.10.2013
  • @Rhizosis: de PostProcess-nek lenne getSubOrder() módszere, nem? Mert különben az elfogadott megoldás sem működne, mert a T-nak csak akkor lenne getSubOrder() metódusa, ha az PostProcess-ben van. 18.10.2013
  • Új anyagok

    A rádiógomb ellenőrzött eseményének használata a jQueryben
    Ebben a cikkben látni fogjuk, hogyan kell dolgozni a jquery választógombbal ellenőrzött eseményeivel. A választógombok HTML gombok, amelyek segítenek kiválasztani egyetlen értéket egy csoportból...

    Körkörös függőségek megoldása terraformban adatforrásokkal – lépésről lépésre
    Mi az a körkörös függőségek Dolgozzunk egy egyszerű eseten, amikor az SQS-sor és az S3-vödör közötti körkörös függőség problémája van egy egymástól függő címkeérték miatt. provider..

    Miért érdemes elkezdeni a kódolást 2023-ban?
    01100011 01101111 01100100 01100101 — beep boop beep boop Világunk folyamatosan fejlődik a technológia körül, és naponta fejlesztenek új technológiákat a valós problémák megoldására. Amint..

    🎙 Random Noise #2  – Örökbefogadás és hit
    az analitika íratlan világának gondozása Szeretné, hogy ezek a frissítések a postaládájába kerüljenek? Iratkozzon fel itt . "Ha önvezető autókat gyártanak, akkor mi miért ne..

    A legrosszabb politika és prediktív modellek májátültetésre jelöltek számára az Egyesült Államokban
    A máj (vagy óangolul lifer) az emberi test legnehezebb belső szervére utal, amely csendesen működik a nap 24 órájában. Mit csinál a máj? 500 feladatot hajt végre a szervezet egészségének..

    5 webhely, amely 2022-ben fejleszti front-end fejlesztői készségeit
    Frontendmentor.io A tényleges projektek létrehozásával a Frontendmentor.io segítséget nyújt a front-end kódolási képességeinek fejlesztésében. A kódolást azután kezdheti meg, hogy..

    Mikor kell használni a Type-t az interfészhez képest a TypeScriptben?
    A TypeScript a JavaScript gépelt szuperkészlete, amely statikus gépelést ad a nyelvhez. Ez megkönnyíti a robusztus és karbantartható kód írását azáltal, hogy a hibákat a fordítási időben..