| Tárgy, csoport: | Programozási nyelvek II. Java (BSc) |
| Oktató: | Németh Boldizsár |
| Feladat: | Első beadandó - MrPostman |
| Határidő: | 2015-11-02, 23:55:00 |
A feladatban levelek kézbesítését fogjuk megoldani. A részfeladatok megoldása során ügyeljünk arra, hogy a megadottakon kívül egyetlen osztály se tartalmazzon más publikus metódust vagy adattagot! Bár nem kötelező, célszerű metódusokat dokumentációs megjegyzéssel dokumentálni.
A megoldást egyetlen zip állományként kell feltölteni, amely tartalmazza a csomagnak megfelelő könyvtárszerkezetben az összes forráskódot. A fordítás során létrejövő class állományokat viszont nem szabad már mellékelni! A fordításhoz minimum a Java Standard Edition 7 használata kötelező.
A kész megoldást az innen letölthető tesztelővel lehet kipróbálni. Ezt a lefordított class fájlokkal a következő módon lehet futtatni:
$ java Test
Egy postának elsődleges feladata, hogy leveleket kézbesítsen. Egy levélnek van feladója, címzettje és tartalma.
A feladót és címzettet egy-egy címmel ábrázoljuk. Egy cím az országból, városból, utcából és házszámból áll.
A leveleket postások kézbesítik, akik egy adott utcában kivisznek egy levelet, illetve eldöntik, hogy jó-e a címzett. A postás tudja, hogy az ő utcájában hány páros és hány páratlan számú házszám van. Ez alapján vagy kikézbesíti a levelet vagy visszaadja a hivatalnak a rossz címzés miatt. Ha visszaküldéskor kiderül, hogy a feladó sem található, akkor a postahivatalnok mérgében összetépi a levelet.
A postának vannak elosztó központjai (hivatalai): minden országban van egy országos, és számos városi hivatal. Egy országnak egy postája van, és számos ország létezik. Az országos hivatalok kapcsolatban állnak más országos hivatalokkal és az országuk városi hivatalaival. A városi hivatalok az országos hivatalukkal állnak kapcsolatban.
A városi hivatalok utca alapján eldöntik, hogy melyik postás tudja kivinni a levelet, és kapcsolatban állnak az országos hivatallal: onnan kapnak leveleket, hogy kikézbesítsék a megfelelő postással. Ha egy postás nem tudja kikézbesíteni a levelet, akkor visszaviszi a városi hivatalba, az pedig visszaküldi a feladónak. Egész pontosan: ha ugyanabban a városban a címzett és a feladó, akkor egyszerű a helyzet: meg kell keresni a postást, aki a feladónak kézbesíteni tudja a levelet. Ha külön városban vannak: el kell küldeni a levelet az országos hivatalnak. Ha másik országban vannak, akkor sincs baj, mert az országos hivatalok kapcsolatban vannak egymással, az egyik átküldheti a levelet a másiknak.
A levelet a feladó egy tetszőleges városi hivatalban adhatja fel, egyszerűen bedobva a postaládába. A feladat a levelek feldolgoztatása.
A post.mail csomagban hozzuk létre az Address osztályt! Ez fogja a címeket ábrázolni. Az Address privát adattagjai a következők:
Szöveg típusú ország, város, utca (country, city, street).
short típusú házszám (number).
Az Address osztálynak legyen egy konstruktora, mely paraméterül várja az adattagok kezdeti értékét, és inicializálja az adattagokat! Emellett minden adattagjához tartozzon egy-egy paraméter nélküli metódus, mely visszaadja az adattag értékét! Például a country-hoz legyen getCountry() metódus, a city-hez legyen getCity() és így tovább.
Ugyanebben a post.mail csomagban hozzuk létre a Letter osztályt is, mely a kézbesítendő leveleket fogja ábrázolni! Egy Letter objektumnak legyenek a következő privát adattagjai:
Address típusú küldő (sender) és címzett (recipient).
Szöveg típusú tartalom (content).
Logikai értékű delivered és destroyed, melyek azt jelölik, hogy a levél kézbesítve lett-e vagy szét lett-e tépve. Ezek értéke kezdetben logikai hamis.
Egy logikai értékű returningToSender, mely jelöli, hogy a levelet sikerült-e eljuttatni a címzetthez. Ez kezdetben logikai hamis értékű, de ha kézbesítés során a postás rájön, hogy a címzett nem található, akkor logikai igazra vált.
A Letter osztály emellett definiálja a következő publikus metódusokat:
Egy konstruktort, mely paraméterül várja a levél címzettjét, a feladóját és a tartalmát, és ezekkel inicializálja az adattagokat. Kezdetben a returningToSender, destroyed és a delivered értéke hamis.
Egy címmel (Address) visszatérő whereToDeliver() metódust, mely visszaadja, hogy kinek kell kézbesíteni a levelet. Ha a returningToSender értéke logikai hamis, akkor ez az eredeti címzett (recipient) lesz, különben pedig a feladó (sender).
Egy logikai értékkel visszatérő isReturningToSender() metódust, mely visszaadja a returningToSender aktuális értékét és egy visszatérési értékkel nem rendelkező backToSender() metódust, mely a returningToSender mező értékét igazra állítja.
Egy logikai értékkel visszatérő isDelivered() metódust, mely visszaadja a delivered mező értékét és visszatérési érték nélküli delivered() metódust, mely a delivered mezőt igaz értékűre állítja.
Egy logikai értékkel visszatérő isDestroyed() metódust, mely visszaadja a destroyed mező értékét és egy visszatérési érték nélküli destroy() metódust, mely a destroyed mezőt igaz értékűre állítja.
Definiáljuk a postást ábrázoló Postman osztályt a post csomagban! Egy postás tudja, hogy melyik utca tartozik hozzá és abban az utcában melyik a legnagyobb páratlan és páros házszám. Egy Postman objektum adattagjai tehát a következők:
Egy publikus, nem módosítható (final), szöveg típusú utcanév (street).
Privát, egész típusú (int) legnagyobb páratlan és páros házszám (lastOdd és lastEven).
Definiáljuk továbbá a következő publikus metódusokat:
Egy konstruktort, mely paraméterül várja az utcanevet, a legnagyobb páros és páratlan házszámokat, és ezekkel inicializálja az adattagokat.
Egy logikai értékkel visszatérő deliver() metódust, mely paraméterül kap egy levelet. Ha a postás kézbesíteni tudja a levelet, akkor a deliver() igazat ad vissza, különben pedig hamisat. A postás abban az esetben tudja kézbesíteni a levelet, ha van legalább akkora házszám az utcában, mint amekkora a levélen szerepel (getNumber()). Ez persze attól függ, hogy a címzett páros vagy páratlan házszám alatt lakik.
Definiáljuk a városi hivatalt ábrázoló Municipal osztályt az office csomagban a post csomagon belül! A városi hivatal számon tartja a székhelyét, az országos postahivatalt, a postásait, és emellett van egy postaládája is, ahova a városban élők bedobhatják a leveleiket, melyet a városi hivatal aztán kézbesít. Az adattagok tehát a következők:
Egy publikus, nem módosítható (final), szöveg típusú székhely (settlement).
A privát, National típusú országos hivatal (superior).
A privát, nem módosítható (final) postások sorozata (postmen), mely egy Postman objektumokat tároló ArrayList referencia.
A privát, nem módosítható (final) postaláda (mailbox), mely levelek láncolt listája (LinkedList).
Definiáljuk továbbá a következő metódusokat is:
Egy publikus konstruktort, mely paraméterül várja az országos hivatalt és a székhelyet, és ezekkel inicializálja a settlement és superior adattagokat. Ne feledkezzünk meg a postások sorozatáról (postmen) és a levelesládáról (mailbox) sem, melyek kezdetben üres lesznek.
Egy publikus, logikai értékkel visszatérő hirePostman() metódust, mely paraméterül vár egy utcanevet és az utcában található legnagyobb páros és páratlan házszámot. Amennyiben a hivatalnál még nincs olyan postás, akinek az utcája azonos a paraméterül kapott utcanévvel, úgy hozzunk létre egy új Postman objektumot, szúrjuk a postások sorozatának végére, és adjunk vissza logikai igaz értéket! Ellenkező esetben (tehát, ha már van postása az utcának), adjunk vissza logikai hamis értéket!
Egy privát, visszatérési érték nélküli returnOrDestroy() metódust, mely paraméterül vár egy levelet. Ha a levél úton van vissza a feladónak (isReturningToSender() igazat ad), akkor megsemmisíti a levelet annak destroy() metódusával. Különben megjelöli a levelet annak backToSender() metódusával, és beteszi a postaládába (mailbox).
Egy privát, visszatérési érték nélküli dispatchLocally() metódust, mely paraméterül vár egy levelet, melyről tudjuk, hogy a városban kell kézbesíteni. Ehhez a következő lépések szükségesek:
Keressük meg a postást, akihez tartozik az az utca, ahova a levelet el kell vinni. Ha nem találtunk ilyen postást, akkor minden bizonnyal a cím rossz, visszaküldjük a feladónak vagy megsemmisítjük a returnOrDestroy() metódus meghívásával.
Ha találtunk postást, aki ki tudja vinni a levelet, adjuk oda neki a deliver() metódusának meghívásával! A deliver() visszaadja, hogy sikerült kézbesíteni a levelet vagy sem. Amennyiben sikerült, úgy készen vagyunk. Amennyiben nem sikerült, visszaküldjük a feladónak vagy megsemmisítjük a levelet returnOrDestroy() metódussal.
Egy, a csomagon belül látható (,,package-private''), visszatérési érték nélküli dispatch() metódust, mely egy kézbesítendő levelet vár paraméterül. Ha a levelet a városban kézbesíteni, akkor a dispatchLocally() kézbesítsük. Különben a levelet más országba vagy városba kell eljuttatni, így átadjuk az országos hivatalnak (superior) annak dispatch() metódusával.
Egy publikus, visszatérési érték nélküli post() metódust, mely paraméterül várja levelek fix méretű tömbjét, és minden levelet betesz a postaládába (mailbox).
Egy publikus, visszatérési érték nélküli deliverLetters(), mely a dispatch() metódust használva kikézbesíti az összes levelesládában (mailbox) található levelet. Ne felejtsük el eltávolítani a levelesládából a kikézbesített leveleket!
Definiáljuk szintén az office csomagban a National osztályt, mely az országos hivatalt fogja ábrázolni! Egy országos hivatal ismeri más országok országos hivatalait, és a saját országának városi hivatalait. Az adattagok tehát a következők:
Egy publikus, nem módosítható (final), szöveg típusú ország (country). Ez tárolja az ország nevét, ahol az országos hivatal található.
Más országok ismert országos hivatalai (contacts), mely egy ArrayList referencia. A láthatóság legyen privát, és legyen a mező nem módosítható (final).
Az országon belüli városi hivatalok (subordinates), mely szintén egy ArrayList referencia. A láthatóság itt is privát, és az adattag nem módosítható (final).
Definiáljuk emellett az alábbi metódusokat:
Egy publikus konstruktort, mely paraméterül várja az ország nevét, ahol a hivatal található, és inicializálja ezzel a country tagot. A contacts és a subordinates sorozatok legyenek kezdetben üresek.
Egy privát, National referenciával visszatérő findContact() metódust, mely paraméterül kap egy országnevet, és kikeresi a hozzá tartozó National referenciát a contacts sorozatból. Ha nincs ilyen referencia, adjunk vissza null-t!
Egy publikus, logikai értékkel visszatérő addContact() metódust, mely paraméterül vár egy országos hivatalt. Vizsgáljuk meg a findContact() metódussal, hogy az ismert országos hivatalok között szerepel-e olyan, amelyik ugyanabban az országban található, mint a paraméterül adott hivatal! Amennyiben szerepel, úgy adjunk vissza logikai hamis értéket, ellenkező esetben vegyük fel az ismert hivatalok közé a paraméterül kapott hivatalt, és adjunk vissza logikai igaz értéket!
Egy privát, Municipal referenciával visszatérő findSubordinate() metódust, mely paraméterül vár egy székhelyet, és kikeresi a hozzá tartozó városi hivatalt a subordinates sorozatból. Hasonlóan a findContact()-hoz, itt is adjunk vissza null-t, ha nem találtunk a székhelyen hivatalt!
Egy publikus, logikai visszatérési értékű addSubordinate(), mely paraméterül vár egy városi hivatalt. Vizsgáljuk meg a findSubordinate() metódussal, hogy az ismert városi hivatalok között szerepel-e olyan, amelyiknek a székhelye ugyanott található, mint a paraméterül kapott hivatalé! Amennyiben szerepel, adjunk vissza logikai hamis értéket, ellenkező esetben vegyük fel a városi hivatalok közé a paraméterül kapott hivatalt, és adjunk vissza logikai igaz értéket!
Egy privát, visszatérési érték nélküli returnOrDestroy() metódust, mely paraméterül vár egy levelet. Ha a levél úton van vissza a feladónak (isReturningToSender() igazat ad), akkor megsemmisíti a levelet annak destroy() metódusával. Különben megjelöli a levelet annak backToSender() metódusával és rögtön visszaküldi a feladónak az alábbi dispatch() metódus meghívásával.
Egy publikus, visszatérési érték nélküli dispatch() metódust, mely paraméterül vár egy kézbesítendő levelet, és továbbítja egy városi hivatalnak, ha a levelet az országon belül kell kézbesíteni, vagy pedig egy másik országos hivatalnak, ha a levél címzettje külföldi. Ezt több lépésben végezzük el:
Először is kérdezzük le a levél whereToDeliver() metódusával, hogy hova is kell elvinni a levelet!
Vizsgáljuk meg, hogy a célország azonos-e az országgal, ahol a hivatal található! Két eset lehetséges:
Ha a két ország azonos, keressük ki a findSubordinate() metódussal annak a városnak a hivatalát, ahova a levelet el kell vinni! Ha találtunk ilyen hivatalt, akkor megkérjük, hogy kézbesítse a levelet azáltal, hogy meghívjuk a városi hivatal dispatch() metódusát. Ha nincs ilyen hivatal, akkor a cím minden bizonnyal rossz, és a returnOrDestroy() metódussal visszaküldjük vagy megsemmisítjük a levelet.
Ha a cél egy másik ország, akkor keressük meg annak az országnak az országos hivatalát a findContact() metódussal! Ha találtunk ilyen hivatalt, akkor megkérjük, hogy kézbesítse a levelet azáltal, hogy meghívjuk a dispatch() metódusát. Ha nincs ilyen hivatal, akkor a cím minden bizonnyal rossz, és a returnOrDestroy() metódussal visszaküldjük vagy megsemmisítjük a levelet.
A beadott megoldásokhoz a beadás után még hozzászólások írhatóak.