1. Interfészek bemutatása

A mai nap a tudásé. Egy másik új és érdekes téma az interfészek.

Az interfész fogalma az absztrakció és a polimorfizmus elvének gyermeke. Az interfész nagyon hasonlít egy absztrakt osztályhoz, amelyben minden metódus absztrakt. Ugyanúgy van deklarálva, mint egy osztály, de mi a interfacekulcsszót használjuk.

interface Feline
{
   void purr();
   void meow();
   void growl();
}

Íme néhány hasznos tény az interfészekről:

1. Interfész deklarálása

interface Drawable
{
   void draw();
}

interface HasValue
{
   int getValue();
}
  1. A kulcsszó helyett classazt írjuk, hogy interface.
  2. Csak absztrakt metódusokat tartalmaz (ne írja be a abstractkulcsszót)
  3. Valójában az interfészek mindenpublic módszerrel rendelkeznek
2. Interfész öröklődése

Egy interfész csak interfészeket örökölhet. De egy felületnek sok szülője lehet. Ennek másik módja az, ha azt mondjuk, hogy a Java interfészek többszörös öröklődésével rendelkezik. Példák:

interface Piece extends Drawable, HasValue
{
   int getX();
   int getY();
}

3. Osztályok öröklése interfészekről

Egy osztály több interfészt is örökölhet (csak egy osztálytól). Ez a implementskulcsszó használatával történik. Példa:

abstract class ChessItem implements Drawable, HasValue
{
   private int x, y, value;
   public int getValue()
   {
      return value;
   }

   public int getX()
   {
      return x;
   }

   public  int getY()
   {
      return y;
   }
}

A ChessItem osztály absztraktnak mondható: az összes örökölt metódust megvalósítja, kivéve a draw. Más szavakkal, az ChessItemosztály egy absztrakt metódust tartalmaz - draw().

extendsA és a kulcsszavak technikai jelentése implementsugyanaz: mindkettő öröklődés. A különbségtétel a kód olvashatóságának javítása érdekében történt. Azt is mondjuk, hogy az osztályok öröklődnek ( via extends), az interfészek pedig implementáltak ( via implements)

4. Változók

Itt van a legfontosabb: a közönséges változókat nem lehet az interfészekben deklarálni (bár a statikusakat igen).

De miért van szükségünk interfészekre? Mikor használják? Az interfészek két erős előnnyel rendelkeznek az osztályokkal szemben:



2. A "módszerek leírásának" elkülönítése a megvalósításuktól.

Korábban azt mondtuk, hogy ha engedélyezni szeretnéd, hogy osztályod metódusait más osztályokból hívják meg, akkor a metódusaidat meg kell jelölni a kulcsszóval public. Ha azt szeretné, hogy egyes metódusok csak az osztályon belül legyenek meghívva, meg kell jelölnie őket a kulcsszóval private. Más szóval, az osztály metódusait két kategóriába osztjuk: "mindenki használhatja" és "csak saját használatra".

Az interfészek tovább erősítik ezt a felosztást. Készítünk egy speciális „mindenki által használható osztályt”, valamint egy „csak saját használatra” második osztályt, amely örökli az első osztályt. Nagyjából így nézne ki:

Előtt Után
class Student
{
   private String name;
   public Student(String name)
   {
      this.name = name;
   }

   public String getName()
   {
      return this.name;
   }

   private void setName(String name)
   {
      this.name = name;
   }
interface Student
{
   public String getName();
}

class StudentImpl implements Student
{
   private String name;
   public StudentImpl(String name)
   {
      this.name = name;
   }

   public String getName()
   {
      return this.name;
   }

   private void setName(String name)
   {
      this.name = name;
   }
}
public static void main(String[] args)
{
   Student student = new Student("Alibaba");
   System.out.println(student.getName());
}
public static void main(String[] args)
{
   Student student = new StudentImpl("Ali")
   System.out.println(student.getName());
}

Osztályunkat két részre osztottuk: egy interfészre és egy osztályra , amely örökli az interfészt . És mi az előnye itt?

Sok különböző osztály megvalósíthatja (örökölheti) ugyanazt az interfészt. És mindegyiknek megvan a maga viselkedése. Például ArrayList LinkedListaz interfész két különböző megvalósítása List.

Így nem csak a különféle implementációkat rejtjük el, hanem magát az implementációs osztályt is (hiszen csak az interfész kell a kódban). Ez lehetővé teszi számunkra, hogy nagyon rugalmasak legyünk: a program futása közben az egyik objektumot lecserélhetjük egy másikra, megváltoztatva az objektum viselkedését anélkül, hogy az összes osztályra hatással lenne, amely azt használja.

Ez egy nagyon erős technika, ha polimorfizmussal kombináljuk. Egyelőre közel sem nyilvánvaló, hogy miért kell ezt tennie. Először több tucat vagy több száz osztályt tartalmazó programokkal kell találkoznia, hogy megértse, az interfészek sokkal könnyebbé tehetik az életét, mint nélkülük.


3. Többszörös öröklődés

Java-ban minden osztálynak csak egy szülőosztálya lehet. Más programozási nyelvekben az osztályoknak gyakran több szülőosztálya is lehet. Ez nagyon kényelmes, de sok problémát is hoz.

A Java készítői kompromisszumra jutottak: megtiltották az osztályok többszörös öröklését, de engedélyezték az interfészek többszörös öröklését. Egy interfésznek több szülőfelülete is lehet. Egy osztálynak több szülőfelülete lehet, de csak egy szülőosztály.

Miért tiltották be az osztályok többszörös öröklését, de engedélyezték az interfészek többszörös öröklését? Az úgynevezett gyémánt öröklődési probléma miatt:

Többszörös öröklés

Amikor a B osztály örökli az A osztályt, nem tud semmit a C és D osztályokról. Tehát az A osztály változóit használja, ahogy jónak látja. A C osztály ugyanezt teszi: az A osztály változóit használja, de más módon. Mindez pedig konfliktust eredményez a D osztályban.

Nézzük a következő egyszerű példát. Tegyük fel, hogy 3 osztályunk van:

class Data
{
   protected int value;
}
class XCoordinate extends Data
{
   public void setX (int x) { value = x;}
   public int getX () { return value;}
}
class YCoordinate extends Data
{
   public void setY (int y) { value = y;}
   public int getY () { return value; }
}

A Data osztály tárolja a valueváltozót. Az XCoordinate leszármazott osztálya ezt a változót használja az érték tárolására x, a YCoordinateleszármazott osztály pedig az érték tárolására y.

És működik. Külön. De ha azt akarjuk, hogy az XYCoordinates osztály örökölje az XCoordinateés YCoordinateosztályokat is, akkor hibás kódot kapunk. Ennek az osztálynak az ősosztályainak metódusai lesznek, de nem fognak megfelelően működni, mert ugyanaz a value variable.

De mivel az interfészek nem tartalmazhatnak változókat, nem lehetnek ilyen konfliktusaik. Ennek megfelelően az interfészek többszörös öröklése megengedett.