Absztrakt órák Java-ban

1. Áttekintés

A szerződés végrehajtása során sok olyan eset fordul elő, amikor a megvalósítás későbbi szakaszait el akarjuk halasztani. Könnyen kivitelezhetjük ezt Java-ban elvont osztályok segítségével.

Ebben az oktatóanyagban megtanuljuk a Java elvont osztályainak alapjait, és milyen esetekben lehetnek hasznosak.

2. Az absztrakt osztályok fő fogalmai

Mielőtt belevágna absztrakt osztály használatába, nézzük meg a legrelevánsabb jellemzőiket:

  • Absztrakt osztályt definiálunk a absztrakt módosítót megelőző osztály kulcsszó
  • Az absztrakt osztály alosztályba sorolható, de nem példányosítható
  • Ha egy osztály meghatároz egyet vagy többet absztrakt módszereket, akkor magát az osztályt kell deklarálni absztrakt
  • Egy absztrakt osztály deklarálhatja absztrakt és konkrét módszereket is
  • Az absztrakt osztályból származtatott alosztálynak vagy az alaposztály összes elvont módszerét kell megvalósítania, vagy pedig absztraktnak kell lennie

E fogalmak jobb megértése érdekében létrehozunk egy egyszerű példát.

Adjuk meg az alap absztrakt osztályunknak egy társasjáték absztrakt API-ját:

public absztrakt osztály BoardGame {// ... terepi deklarációk, konstruktorok public absztrakt void play (); // ... konkrét módszerek}

Ezután létrehozhatunk egy alosztályt, amely megvalósítja a játék módszer:

a public class Checkers kiterjeszti a BoardGame játékot {public void play () {// ... implementáció}}

3. Mikor kell használni az elvont osztályokat

Most, elemezzünk néhány tipikus forgatókönyvet, ahol az absztrakt osztályokat kell előnyben részesítenünk az interfészek helyett és beton osztályok:

  • Néhány általános funkciót egy helyre akarunk foglalni (kód újrafelhasználása), amelyet több, kapcsolódó alosztály megoszt
  • Részben meg kell határoznunk egy API-t, amelyet alosztályaink könnyedén kibővíthetnek és finomíthatnak
  • Az alosztályoknak egy vagy több általános módszert vagy mezőt kell örökölniük védett hozzáférés-módosítókkal

Ne feledjük, hogy ezek a forgatókönyvek jó példák a nyitott / zárt elv teljes, öröklésen alapuló betartására.

Sőt, mivel az absztrakt osztályok implicit módon az alaptípusokkal és altípusokkal foglalkoznak, a polimorfizmus előnyeit is kihasználjuk.

Vegye figyelembe, hogy a kód újrafelhasználása nagyon meggyőző ok az absztrakt osztályok használatára, mindaddig, amíg az osztályhierarchiában megmarad az „is-a” kapcsolat.

És a Java 8 újabb ráncot ad az alapértelmezett módszerekkel, amelyek néha helyettesíthetik egy absztrakt osztály létrehozásának szükségességét.

4. A fájlolvasók mintahierarchiája

Az absztrakt osztályok által az asztalra hozott funkcionalitás tisztább megértése érdekében nézzünk meg egy másik példát.

4.1. Alap absztrakt osztály meghatározása

Tehát, ha több típusú fájlolvasót szeretnénk használni, létrehozhatunk egy absztrakt osztályt, amely összefoglalja a fájlolvasás közös jellemzőit:

public abstract class BaseFileReader {védett útvonal filePath; védett BaseFileReader (Path filePath) {this.filePath = filePath; } public Path getFilePath () {return filePath; } public list readFile () dobja az IOException-t {return Files.lines (filePath) .map (this :: mapFileLine) .collect (Collectors.toList ()); } védett absztrakt Karakterlánc mapFileLine (Karakterlánc); }

Vegye figyelembe, hogy elkészítettük fájl elérési út védve, hogy az alosztályok szükség esetén hozzáférhessenek hozzá. Ami még fontosabb, valamit nem hagytunk: hogyan lehet egy szövegrészt valóban elemezni a fájl tartalmából.

A tervünk egyszerű: bár konkrét osztályainknak nincs külön módja a fájl elérési útjának tárolására vagy a fájl végigjárására, mindegyiknek külön módja lesz az egyes sorok átalakítására.

Első látásra, BaseFileReader feleslegesnek tűnhet. Ez azonban a tiszta, könnyen bővíthető kialakítás alapja. Ebből, könnyen megvalósíthatjuk a fájlolvasó különböző verzióit, amelyek egyedi üzleti logikájukra összpontosíthatnak.

4.2. Alosztályok meghatározása

Természetes megvalósítás valószínűleg a fájl tartalmát kisbetűvé alakítja:

public class LowercaseFileReader kiterjeszti a BaseFileReader {public LowercaseFileReader (Path filePath) {super (filePath); } @Orride public String mapFileLine (String line) {return line.toLowerCase (); }}

Vagy egy másik lehet, amely a fájl tartalmát nagybetűvé alakítja:

public class UppercaseFileReader kiterjeszti a BaseFileReader {public UppercaseFileReader (Path filePath) {super (filePath); } @Orride public String mapFileLine (String line) {return line.toUpperCase (); }}

Amint ezt az egyszerű példát láthatjuk, minden egyes alosztály egyedi viselkedésére összpontosíthat anélkül, hogy meg kellene adni a fájlolvasás egyéb aspektusait.

4.3. Alosztály használata

Végül egy absztrakt osztálytól örökölt osztály használata nem különbözik bármely más konkrét osztálytól:

@Test public void givenLowercaseFileReaderInstance_whenCalledreadFile_thenCorrect () dobja a (z) {URL location = getClass (). GetClassLoader (). GetResource ("files / test.txt") Path path = Paths.get (location.toURI ()) kivételt; BaseFileReader lowercaseFileReader = új LowercaseFileReader (elérési út); assertThat (smallcaseFileReader.readFile ()). isInstanceOf (List.class); }

Az egyszerűség kedvéért a célfájl a src / main / resources / files mappába. Ezért egy alkalmazásosztály betöltőt használtunk a példa fájl elérési útjának lekérésére. Nézze meg bátran az oktatóanyagunkat a Java osztályos rakodóiról.

5. Következtetés

Ebben a gyors cikkben megtanultuk az elvont osztályok alapjait a Java-ban, és mikor kell felhasználni őket az absztrakció elérésére és a közös megvalósítás egyetlen helyre történő beágyazására.

Szokás szerint az ebben az oktatóanyagban bemutatott összes kódminta elérhető a GitHubon.