Translations of this page:

02 - OOP

Úvod

  • 01101 → assembler → procedurální programování → OOP,
  • Assembler - nízkoúrovňový jazyk,
  • Procedury - znovuvyužitelné celky, vstup se realizuje parametry (příp. funkce vrací hodnotu).

Objektově orientované programování - OOP

  • Vychází z pohledu na reálný svět, na základě vlastností a chování objektů se v OOP vytváří software, který odráží tyto vlastnosti a chování.
  • Třídy představují šablony pro návrh objektů, obsahují:
    • Data (atributy - proměnné, konstanty),
    • Chování (metody pracující s daty).

Vlastnosti OOP

Zapouzdření

  • Data nejsou přímo přístupná jako proměnné, přístup se realizuje pomocí metod (setXXX, getXXX, isXXX, hasXXX).
  • Vhodné např. kvůli ošetření rozsahu vstupních hodnot, kontroly jejich správnosti a dalším výpočetním akcím. Např. pokud budete mít v grafické aplikaci objekty reprezentující obdélníky,

bude vhodné, aby barva byla zapouzdřená a v metodě pro její změnu (setColor, setBarva) bylo překreslení tohoto objektu.

  • V Javě - modifikátory přístupu:
    • private - přístup pouze z vlastní třídy,
    • nic, tzv. default - vlastní balíček,
    • protected - vlastní balíček a potomci,
    • public - veřejné, přístup odkudkoli.

Dědičnost

  • Získání vlastností (dat a metod) zděděním od předka.
  • Java - dědit přímo lze pouze z jediné třídy, klíčové slovo extends, pokud není uvedeno je přímým předkem třída Object.
  • Java můžeme mít více přímých předků, které nejsou třídou ani abstraktní třídou, ale jsou rozhraními, klíčové slovo implements.

Například:

public class Obdelnik extends DveDObjekt implements Srafovatelny,Serializable, Comparable{ }

Polymorfismus

  • Jednotné zacházení s „podobnými“ objekty (podobné objekty ~ potomci společného předka).

OOP v Javě

Třídy

  • V jednom souboru právě jedna top public třída (příp. interface), její jméno je shodné se jménem zdrojového souboru (.java), další třídy v souboru pokud jsou na nejvyšší úrovni (=nejsou zapsané v bloku jiné třídy) nesmí být public.
  • Každá třída má konstruktor, který je volán při vytváření instance (destruktor není - Java má garbage collector, ale existuje metoda finalize, kterou volá GC při uvolňování místa. Pozor, nikdo nezaručí, že tato metoda bude zavolána a kdy. Program může skončit bez potřeby uklízení paměti pomocí GC, pak není tato metoda volána).
  • Jsou volány i konstruktory a statické i nestatické inicializátory předků třídy, od které vytváříme instanci.
  • Instance se vytváří klíčovým slovem new, například:
String s = new String("abc");    // proměnná s je typu reference na String
  • Abstraktní třída - třída, od které nechceme či neumíme vytvářet instance. Příklad mějme GrO třídu reprezentující grafický objekt s atributem barva a metodou kresliSe. Tato metoda je abstraktní, její implementaci provedou až potomci (Usecka, Bod, Obdelnik) podle své povahy.
  • Třídy lze do sebe vnořovat. Vnitřní a vnořená třída pak vidí atributy vnější třídy.
  • Příklad deklarace:
package mujBalik1.mujBalik2;
 
[abstract] [public] class PrvniTrida
    [extends Predek]
    [implements Rozhrani1 [, Rozhrani2...]] {
        ... tělo ...
}

Třídy - dědění

  • Každá třída má právě jednoho svého přímého třídního předka (vyjma java.lang.Object), pokud neuvedeme extends, tak je jím právě třída Object.
  • Třída může implementovat více rozhraní, ale také nemusí implementovat žádné. Implementované rozhraní je také předkem.
  • Zjištění, zda-li je „x předkem y“ se provádí pomocí operátoru instanceof.
  • Metody předka jsou dostupné pomocí klíčového slova super.

Třídy - konstruktory

  • Konstruktor je speciální metoda, která
    • složí k inicializaci objektu poté, co jej Java vytvoří,
    • nemá specifikován návratový typ,
    • má jméno shodné se jménem třídy.
  • Volání konstruktoru předka je nutné uvádět jako první, pokud jej neuvedeme Java doplní volání konstruktoru předka bez parametrů (a předek jej samozřejmě musí mít).
  PrvniTrida(int x) {
    super(x);
    // další příkazy
  }

Interface (rozhraní)

  • „plně abstraktní třída“, obsahuje pouze abstraktní metody a statické atributy (příp. vnitřní třídy a interface).
  • Jedno rozhraní může dědit od více rozhraní, použijte klíčové slovo extends.
  • Například Serializable, Runnable (definuje metodu run), …

Příklady

Volání konstruktorů při dědění

  class TridaA {
    TridaA() {
      System.out.println("Class A constructor");
    }
  }
  class TridaB extends TridaA {
    TridaB() {
      System.out.println("Class B constructor");
    }
  }
  class TridaC extends TridaB {
    TridaC() {
      System.out.println("Class C constructor");
    }
 
    public static void main(String[] args) {
      TridaC x = new TridaC();
    }
  }
  // konstruktor předka je volán i když potomek žádný konstruktor
  // nemá definován (protože má implicitní konstruktor)

Přetěžování konstruktorů a metod

  int foo(int x)        { return 1; }
  int foo(double x)     { return 1; }
  int foo(int x, int y) { return 1; }
  int foo(String x)     { return 1; }
  double foo(int x)     { return 1; }  // nelze, koliduje s int foo(int x)

Vnoření třídy do kódu

  public static void main(String[] args) {
      class VnorenaTrida {
          public void call() {
              System.out.println("print called");
          }
      }
      VnorenaTrida vt = new VnorenaTrida();
      vt.call();
  }
  // zde už není VnorenaTrida "známa" (mimo rámec platnosti)

Vnoření třídy do třídy

  public class BigClass {
      private int x = -2;
      private SmallClass sc = new SmallClass();
 
      class SmallClass {
          public void printx() {
              System.out.println(x);
          }
      }
      public void print() {
          sc.printx();
      }
 
      public static void main(String[] args) {
          BigClass bc = new BigClass();
          bc.print();
      }
  }

Kolize interfaců

  interface I1 {    void f();    }
  interface I2 {    int f(int i);    }
  interface I3 {     int f();    }
 
  abstract class CompositeI12 implements I1, I2 {
  }    // ok
 
  abstract class CompositeI123 implements I1, I2, I3 {
  }    // fail
      // funkce f u I1 a I3 mají různé návratové typy

Operátor instanceof

  public class Main implements java.lang.Runnable {
      public void run() { }
          public static void main(String[] args) {
          Main m = new Main();
          if (m instanceof java.lang.Runnable) {
              System.out.println("Is Runnable");
          }
      }
  }

Spuštění této třídy:

  public class Test{
    public static void main(String[] args) {
      Thread t = new Thread(new Main());
        t.start();
      }
  }

Úloha ke zpracování při cvičeních

Realizujte strukturu grafických objektů, implementujte metody posun, meritko, vykresli (vypište na konzoli pozici a velikost grafického objektu).

Class diagram představující požadovanou strukturu tříd

Diskutujte hierarchii tříd, rozmyslete proč je toto schéma nedokonalé.

 
/webdev/www/courses/Y36PJV/data/pages/cviceni/cviceni02.txt · Poslední úprava: 2009/03/12 13:40 autor: balikm
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki