Informatika4-2018/Gyakorlat6

A MathWikiből
A lap korábbi változatát látod, amilyen Gaebor (vitalap | szerkesztései) 2018. október 18., 12:14-kor történt szerkesztése után volt.

Tartalomjegyzék

Overriding

Nem statikus

Ha egy osztályban van egy ugyanolyan szignatúrájú metódus, mint az ősében, akkor beszélünk

  • felülírás, felüldefiniálás
  • override
  • túlterhelés

-ről

public class Parent
{
    float f(float x)
    {
        ...
    }
}
 
public class Child extends Parent
{
    float f(float x)
    {
        ...
    }
}

Ekkor az alábbi f hívások mást adnak vissza, attól függően, hogy hogyan írtuk felül.

Parent parent = new Parent();
Child child = new Child();
 
parent.f(3.14f); // <- szülőben lévő f
child.f(3.14f);  // <- gyerekben lévő f

Viszont ez akkor is így történik, ha minkettőt az ősosztlyként tárolom.

Parent objects = new Parent[2];
objects[0] = new Parent();
objects[1] = new Child(); // leszármazott osztály az ősosztállyá konvertálódik
 
objects[0].f(3.14f); // <- szülőben lévő f
objects[1].f(3.14f);  // <- gyerekben lévő f

Vagyis az íly módon meghívott f őrzi azt, hogy hogyan hoztuk létre az aktuális példányt.

Ez a dinamikus polimorfizmus és a hatását egy felüldefiniált metóduson keresztül láthattuk.

Statikus

Nem ez a helyzet statikus metódusnál.

public class Parent
{
    static float f(float x)
    {
        ...
    }
}
 
public class Child extends Parent
{
    static float f(float x)
    {
        ...
    }
}

Ekkor hiába Child konstruktorral jött létre egy Parent típusú változó, akkor is a Parent.f hívódik meg.

Parent[] objects = new Parent[2];
objects[0] = new Parent();
objects[1] = new Child(); // leszármazott osztály az ősosztállyá konvertálódik
 
objects[0].f(3.14f); // <- Parent.f
objects[1].f(3.14f);  // <- Parent.f

Figyeljük meg, hogy statikus metódust osztályra szoktunk hívni (Parent.f vagy Child.f), ezért warning-ot kapunk, de akkor is ugyanaz történik.

Vagyis a statikus felüldefiniálás elvész, az számít, hogy mely típus statikus metódusát hívjuk, nem pedig az hogy a konkrét példány hogyan jött létre.

Interface

Definiáljuk az alábbi interface-t

public interface Polygon
{
    public float area();
    public void translate(float x, float y);
}

Két osztály implementálja ezt: Square és LineSegment. Valahogy így:

public class Square implements Polygon
{
    private float x_, y_;
    public Square()
    {
        ...
    }
    .
    .
    .
    public float area()
    {
        ...
    }
    public void translate(float x, float y)
    {
        ...
    }
}

Hasonlóan a LineSegment-re (annak mindig 0 a területe).

Ekkor lehetőségünk van ezeket a síkbeli objektumokat egységesen kezelni.

Polygon[] polygons = new Polygon[2];
polygons[0] = new Square(0,0,1);
polygons[1] = new LineSegment();
 
polygons[0].translate(-1,-1);
polygons[1].translate(1,1);

Figyeljük meg, hogy ekkor nem tudok egy Polygon példányt látrehozni, annélkül hogy Square vagy LineSegment ne lenne.

Polygon p = new Polygon(); // <- hiba!

Ez azért van, mert az interface-ek ú.n. absztrakt osztályok, a metódusai (konstruktora is) csak ígéretek arra, hogy van olyan metódusa, de implemntálva nincsen. Vagyis a metódusai a leszármazott osztályokban vannak implementálva.

Személyes eszközök