A második alfejezet vizsgához szükséges célja:

1.1 Fejlesszünk olyan kódot, ami osztályokat (beleértve az absztrakt és a beágyazott osztályok minden típusát), interfészeket és enumokat deklarál és használja a szükséges package és import parancsokat (beleértve a static importot is).

A Javaban való programozás során gyakorlatilag osztályokat és interfészeket hozunk létre. Ezek deklarálása jelentősen befolyásolja a program működését, felépítését. Néhány alapvető szabály:

  • Egy forrás fájl csak egy publikus osztály deklarációt tartalmazhat.
  • Kommentek bárhol előfordulhatnak a forrásban, kezdődhetnek sor közben, vagy sor elején is.
  • Ha egy fájl tartalmaz egy publikus osztály deklarációt, akkor a fájl nevének meg kell egyeznie ezen osztály nevével (pl.: public class Dog { } a Dog.java forrásfájlban kell legyen).
  • Ha az osztály egy csomag része, akkor a package parancsnak a forrás első sorában kell lennie, az esetleges importok előtt.
  • Ha használunk import parancsokat, akkor azoknak a package definíció után és az osztály deklaráció előtt kell lenniük. Ha nincs sem package, sem import definíció, akkor az osztály deklarációval kezdődik a forrás fájl.
  • Egy fájlon belüli package és import parancsok minden osztályra vonatkoznak, amelyek ezen fájlban vannak deklarálva. Más szóval nem lehetséges azonos forráson belül két különböző packagebe tartozó osztályt definiálni, hasonlóan nem lehet őket különböző import parancsokkal ellátni.
  • Egy forráson belül több nem-publikus osztályt is lehet deklarálni.
  • Az olyan forrás fájlnak, mely csak nem-publikus osztály deklarációkat tartalmaz eltérhet a neve minden osztály elnevezésétől.

Osztály deklaráció és módosítók

A legegyszerűbb osztály deklaráció, amely le is fordul:

class MyClass { }

 

Az osztályt, hasonlóan a metódusokhoz és osztályváltozókhoz, módosítókkal - modifierekkel láthatunk el. Ezeket két csoportra oszthatjuk:

  • Access modifiers: public, protected, private
  • Non-access modifiers (osztályok esetén): strictfp, final, abstract

 

Az access modifier-ek gyakorlatilag kulcsszavak, amik szabályozzák a láthatóságot, meghatározzák az access controlt. A dolog érdekessége, hogy míg 4 access control van, addig hozzá csak az említett 3 access modifier van. A negyedik control ugyanis a default, vagy package - csomag szintű access. Ha ezt szeretnénk használni, akkor egyszerűen nem írunk access modifiert. Alapértelmezetten tehát minden osztály package szintű accessel rendelkezik, de használva a három modifier egyikét, ez megváltoztatható. Egészen pontosan osztályok esetén csak a public használható, mert - mint majd egy későbbi fejezetben látni fogjuk - a protectednek és a private-nak nincs értelme. Marad tehát a default és a public.

Megjegyzés: A Java csomag centrikus nyelv, ami azért hasznos, mert így a különböző cégek, különböző programjainak és azok különböző részeinek osztályai egyértelműen elkülöníthetőek, normális esetben nem fordulhat elő névütközés. Az általános szabály a csomagok elnevezésére a fordított domain név, majd a project neve, végül ha szükséges, annak részegysége. Így például: com.company.project.client. Adott csomag részegysége fájl szinten könyvtárat jelöl, a csomagon belüli osztályok forrása pedig az abban lévő fájlokat.

Osztály access

Mit is jelent az, hogy A osztály hozzáfér B osztályhoz (másnéven B látható A számára)? Azt jelenti, hogy A a következő három dolgot teheti meg:

  • Létre tud hozni egy példányt B-ből.
  • Ki tudja terjeszteni B-t, azaz gyermek osztálya tud lenni.
  • Hozzáfér B metódusaihoz és változóihoz, attól függően, hogy azok milyen access controllal rendelkeznek.

Gyakrolatilag tehát B access controllja meghatározza az ő láthatóságát más osztályok felé. Amennyiben más osztály nem látja B-t, úgy B metódusainak és változóinak saját access controllja már nem is számít.

Default access

Ha egy osztály deklarációját nem látunk el modifierrel, úgy default, vagy package accesst fog kapni. Erre úgy kell gondolni, hogy csak a vele azonos osztályban lévő osztályok számára lesz látható. Egy példa:

package cert;
class Beverage { }

Másik forrás:

package exam.stuff;
import cert.Beverage;
class Tea extends Beverage { }

Az első fájl sikeresen lefordul, a második azonban nem, mert számára nem látható osztályt próbál importálni és azt kiterjeszteni. Ilyesmi hibaüzenetet kapunk:

Can't access class cert.Beverage. Class or interface must be public, in same package, or an accessible member class.
import cert.Beverage;

A megoldás az lehet, hogy azonos csomagba helyezzük őket, vagy a Beverage osztályt public-ként deklaráljuk. A vizsgán érdemes figyelni a láthatóságot, mert előfordul, hogy egy kérdésnél meg sem kell vizsgálni a feladatban szereplő kód logikáját, hanem rögtön azt a választ adhatjuk, hogy a kód nem fordul.

Public access

Ha egy osztályt ellátjuk a public kulcsszóval, akkor minden java osztály számára láthatóvá válik. Persze ha más csomagból szeretnénk használni, akkor nem szabad megfeledkezni az importálásáról. Az előző példa megoldása tehát:

package cert;
public class Beverage { }

Más (nem hozzáférést szabályozó) osztály módosítók

Módosíthatjuk az osztály deklarációt a strictfp, abstract, vagy final kulcsszóval is. Ezeket az access modifierektől függetlenül és egymás mellett is használhatjuk. Természetesen nem ilyen egyszerű, mert itt is van kivétel: nem használhatjuk együtt a final és az abstract kulcsszót.

A strictfp kulcsszó ismerete nem szükséges a viszgához, elég róla annyit tudni, hogy használhatjuk metódusok definíciója előtt is, és osztályok esetén is. Ez utóbbi esetben azt határozzuk meg, hogy az osztály minden metódusa megfelel az IEEE 754 szabvány lebegőpontos számok szabályainak. Különben eltérő platformokon ezek eltérőek lehetnek.

Final osztályok

Ha a final kulcsszót használjuk, akkor azzal azt deklaráljuk, hogy az osztály nem kiterjeszthető, azaz véglegesítjük. A gyakorlatban ezt ritkán kell megtennünk (hiszen az objektum orientált programozás alapvető tulajdonságának, a kiterjeszthetőségnek mond ellent), általában csak akkor, ha biztosra akarunk menni, hogy más programozó véletlenül sem módosít osztályunk működésén és nem készít alternatív gyermek osztályt. Leginkább a Java alaposztályok, mint a String vannak final-ként deklarálva, hogy megóvjanak az ilyen elemi osztályok kiterjesztéséből adódó hibáktól. Ne feledjük, hogy ha egy osztályt final-ként deklarálunk, akkor az esetleges hibákat forráskód nélkül már más nem tudja javítani.

Az előző példát folytatva:

package cert;
public final class Beverage {
    public void importantMethod() { }
}

 

Ha megpróbáljuk lefordítani a Tea osztályt:

package exam.struff;
import cert.Beverage;
class Tea extends Beverage { }

 

Akkor a következő fordítási hibát kapjuk:

Can't subclass final classes: class cert.Beverage
class Tea extends Beverage {
1 error

Absztrakt osztályok

Az absztrakt osztály nem példányosítható, csak kiterjeszthető. Ilyen módon nagyjából az ellentéte a finalnek. Érdemes olyan osztályokat abstractként deklarálni, amelyek vannak annyira általánosak, hogy noha tartalmazhatnak nem absztrakt eljárásokat, de várhatóan specializált gyermek osztályok készülnek hozzá. Például egy Car osztály túl összetett lenne, ha minden típus speciális tulajdonságát tárolni akarnánk, ehelyett gyermek osztályokat készítünk.

abstract class Car {
    private double price;
    private String model;
    private String year;
    public abstract void goFast();
    public abstract void goUpHill();
    public abstract void impressNeighbors();
}

 

Az absztrakt osztály fordítható és futtatható, mindaddig, amíg nem akarjuk példányosítani. Ebben az esetben ilyen hibaüzenetet kapunk:

AnotherClass.java:7: class Car is an abstract class. It can't be instantiated.
    Car x = new Car();
1 error

 

Figyeljünk arra, hogy az abstract kulcsszóval ellátott eljárások nem kapcsos zárójellel végződnek, hanem pontosvesszővel. Ez deklarálja a metódust, de a konkrét definíciót a gyermek osztálynak kell elvégeznie - amennyiben az nem absztrakt. Ha egy osztály legalább egy absztrakt metódust tartalmaz, akkor az osztályt is abstractként kell megjelölnünk. Ellenben az absztrakt osztály tartalmazhat nem absztrakt függvényeket is. Ezeket minden gyermek osztály örökölni fogja, azokban elegendő lesz az absztrakt illetve az opcionális egyéb metódust definiálni.

Jelentésében tehát annyira eltér az abstract és final, hogy azokat párban használva fordítási hibát kapunk.

A bejegyzés trackback címe:

https://scjp.blog.hu/api/trackback/id/tr112509482

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

süti beállítások módosítása