Szia! A mai leckét szenteljük a kapszulázásnak, és rögtön kezdjük is példákkal :) Itt van egy közönséges szódagép . Egy kérdésem lenne hozzád: hogyan működik? Próbáljon meg részletes választ adni: honnan származik a csésze, hogyan tartják fenn a belső hőmérsékletet, hol tárolják a jeget, honnan tudja a gép, hogy melyik szirupot kell hozzáadni stb.? Valószínűleg nem kap választ ezekre a kérdésekre. Elég jogos, hiszen nem mindenki használ ilyen gépeket. Manapság nem annyira népszerűek. Próbáljunk egy másik példát mondani. Valami, amit biztosan sokszor használsz minden nap. Ó, itt egy ötlet! Mondja el, hogyan működik a Google keresőművek. Pontosan hogyan keresi a beírt szavakkal kapcsolatos információkat? Miért vannak bizonyos eredmények előkelő helyen, mások miért nem? Annak ellenére, hogy minden nap használja a Google-t, valószínűleg nem tudja. De nem számít. Ezt nem kell tudnod. Beírhat lekérdezéseket a keresőmotorba anélkül, hogy gondolkodna a működésén. Vásárolhat szódát egy gépből anélkül, hogy tudná, hogyan működik. Lehet autót vezetni anélkül, hogy megértené a belső égésű motor működését, és egyáltalán nem ismerné a fizikát, még általános iskolai szinten is. Mindez az objektum-orientált programozás egyik fő elvének, a tokozásnak köszönhetően lehetséges. Az objektum-orientált programozásról (OOP) szóló különféle cikkek olvasása során biztosan találkoztál azzal a ténnyel, hogy a programozás két általános fogalmat foglal magában: a beágyazást és a rejtést . A szerzők pedig a "kapszulázás" szót egy, majd más dologra használják. Mindkét kifejezést megvizsgáljuk, hogy teljes megértését elnyerje. A programozásban a beágyazás eredeti jelentése az adatok egyetlen egységbe (azaz egy "kapszulába") való kötegelése az adatokon működő metódusokkal együtt . A Java nyelven az osztály a beágyazás egysége. Egy osztály adatokat (mezőket) és módszereket is tartalmaz az adatokkal való munkavégzéshez.Ez nyilvánvalóan helyes megközelítésnek tűnhet számodra, de más programozási paradigmákban minden másképp van elrendezve. Például a funkcionális programozásban az adatokat szigorúan elválasztják a rajtuk végzett műveletektől. Az OOP-ban a programok kapszulákból vagy osztályokból állnak, amelyek adatokból és az adatokkal való munkavégzéshez szükséges függvényekből állnak. Most beszéljünk a rejtőzködésről . Hogy van az, hogy mindenféle összetett eszközt használunk anélkül, hogy megértenénk azok felépítését vagy működését? Egyszerű: készítőik egyszerű és kényelmes felületet biztosítottak számunkra. Egy szódagépen a felület a panelen található gombok. Egy gomb megnyomásával kiválaszthatja a csésze méretét. Egy másik megnyomásával kiválaszthatja az ízt. Egy harmadik felelős a jég hozzáadásáért. És csak ennyit kell tennie. A gép belső felépítése nem számít. Ami számít, az az, hogy úgy van megtervezve, hogy a felhasználónak három gombot kell megnyomnia, hogy szódát kapjon . Ugyanez igaz az autókra is. Nem számít, mi történik odabent. A lényeg az, hogy a jobb pedál megnyomásakor az autó előre halad, a bal pedált megnyomva pedig lassít. Ennyit jelent a rejtőzködés. A program minden „belseje” el van rejtve a felhasználó elől. A felhasználó számára ez a felesleges, felesleges információ. A felhasználónak a végeredményre van szüksége, nem a belső folyamatra. Nézzük az
Auto
osztályt példaként:
public class Auto {
public void go() {
/* Some complicated things happen inside the car.
As a result, it moves forward */
}
public void brake() {
/* Some complicated things happen inside the car.
As a result, it slows down. */
}
public static void main(String[] args) {
Auto auto = new Auto();
// From the user's perspective,
// one pedal is pressed and the car accelerates.
auto.gas();
// The other is pressed, and the car slows down.
auto.brake();
}
}
Így néz ki a megvalósítás elrejtése egy Java programban. Ugyanúgy, mint a való életben: a felhasználót interfésszel (módszerekkel) látják el. Ha a felhasználónak autóra van szüksége egy programban egy művelet végrehajtásához, akkor csak meghívja a kívánt metódust. Ami ezeken a módszereken belül történik, az felesleges. A lényeg, hogy minden úgy működjön, ahogy kell. Itt a megvalósítás elrejtéséről beszélünk . Ezen kívül a Java is rejti az adatokat . Erről írtunk a getterekről és szetterekről szóló leckében , de a koncepció áttekintése nem árt. Például van egy Cat
osztályunk:
public class Cat {
public String name;
public int age;
public int weight;
public Cat(String name, int age, int weight) {
this.name = name;
this.age = age;
this.weight = weight;
}
public Cat() {
}
public void sayMeow() {
System.out.println("Meow!");
}
}
Talán emlékszel az osztály problémájára az előző leckéből? Ha nem, akkor most emlékezzünk rá. A probléma az, hogy adatai (mezői) mindenki számára nyitva állnak – egy másik programozó könnyen létrehozhat egy névtelen macskát, amelynek súlya 0 és -1000 éves:
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "";
cat.age = -1000;
cat.weight = 0;
}
Talán gondosan figyelemmel kísérheti, hogy valamelyik munkatársa készített-e érvénytelen állapotú objektumokat, de sokkal jobb lenne még az ilyen "érvénytelen objektumok" létrehozásának lehetőségét is kizárni. A következő mechanizmusok segítenek az adatok elrejtésében:
- hozzáférés módosítók ( privát , védett , csomag alapértelmezett )
- getterek és szetterek
- Egy objektum megfelelő állapotának ellenőrzése. Erre volt példa fent. A setter és a privát módosító biztosítja, hogy programunkban ne legyenek 0 súlyú macskák.
- Felhasználóbarát interfész révén. Csak a módszerek maradnak "kitéve" a külvilágnak. A metódusok meghívása elegendő az eredmény eléréséhez – egyáltalán nem kell elmélyedni a működésük részleteiben.
- A kódmódosítások nem érintik a felhasználókat. A módszereken belül minden változtatást végrehajtunk. Ez nem érinti a módszer felhasználóját: ha a megfelelő kód korábban "auto.gas()" volt a gázpedál lenyomásakor, akkor továbbra is az lesz. Az a tény, hogy valamit megváltoztattunk a gas() metóduson belül, a felhasználó számára láthatatlan marad: a hívó egyszerűen megkapja a kívánt eredményt.
GO TO FULL VERSION