Konstruktory

  • Konstruktury jsou speciální metody volané při vytváření nových instancí (=objektů) dané třídy.

  • Typicky se v konstruktoru naplní (inicializují) proměnné objektu.

  • Konstruktory lze volat jen ve spojení s operátorem new k vytvoření nové instance třídy — nového objektu, evt. volat z jiného konstruktoru

Konstruktory — syntaxe

public class Person {
   private String name;
   private int age;
   // konstruktor se dvěma parametry
   // - inicializuje hodnoty proměnných ve vytvořeném objektu
   public Person(String name, int age) {
      this.name = name;
      this.age = age;
   }
   ...
}

Konstruktory — použití

Příklad využití tohoto konstruktoru:

...
Person pepa = new Person("Pepa z Hongkongu", 105);
...

Toto volání vytvoří objekt pepa a naplní ho jménem a věkem.

Konstruktory — shrnutí

Jak je psát a co s nimi lze dělat?

  • Nemají návratový typ (ani void - to už vůbec ne !!!);

  • mohou mít parametry;

  • mohou volat konstruktor rodičovské třídy pomocí klíčového slova super, které zastupuje jméno konstruktoru předka — to nás bude zajímat, jakmile začneme používat dědičnost.

  • Konstruktor předka se volá v každém případě, vždy jen jako svůj první příkaz a to, i když neuvedeme super() — pak se bezparametrický konstruktor zavolá automaticky.

Přetěžování metod

  • Jedna třída může mít více metod se stejnými názvy, ale různými parametry.

  • Pak hovoříme o tzv. přetížené (overloaded) metodě.

  • Nelze přetížit metodu pouze změnou typu návratové hodnoty.

Přetěžování — příklad

Ve třídě Account přetížíme metodu transferTo.

  • Přetížená metoda převede na účet příjemce celý zůstatek z účtu odesílatele:

    public void transferTo(Account whereTo) {
       whereTo.add(balance);
       balance = 0;
    }

Ve třídě Account nyní koexistují dvě různé metody se stejným názvem, ale jinými parametry.

Pozn: I když jsou to teoreticky dvě úplně různé metody, pak když už se jmenují stejně, měly by dělat něco podobného.

Přetěžování — příklad (2)

Často přetížená metoda volá jiné "vydání" metody se stejným názvem:

public void transferTo(Account whereTo) {
   transferTo(whereTo, balance);
}

Toto je jednodušší, přehlednější, udělá se tam potenciálně méně chyb. Lze doporučit. Je to přesně postup divide-et-impera, rozděl a panuj, dělba práce mezi metodami!

Přetěžování — příklad (3)

  • Je ale otázka, zdali převod celého zůstatku raději nenapsat jako nepřetíženou, samostatnou metodu, např.:

    public void transferAllMoneyTo(Account whereTo) {
       transferTo(whereTo, balance);
    }
  • Je to o něco instruktivnější, ale přibude další identifikátor — název metody — k zapamatování. Což může být výhoda (je to výstižné) i nevýhoda (musíme si pamatovat další).

Odkazy na objekty (instance)

Deklarace proměnné objektového typu sama o sobě ještě žádný objekt nevytváří.

To se děje až příkazem (operátorem) new:

  • Proměnné objektového typu jsou vlastně pouze odkazy na dynamicky vytvářené objekty.

  • Přiřazením takové proměnné zkopírujeme pouze odkaz. Na jeden objekt se odkazujeme nadále ze dvou míst. Nezduplikujeme tím celý objekt!

Přiřazování objektových proměnných (1)

V následující ukázce vytvoříme dva účty:

  • Odkazy na ně budou primárně v proměnných petrsAccount a ivansAccount.

  • V proměnné u nebude primárně odkaz na žádný účet.

  • Pak do ní přiřadíme (p = petrsAccount;) odkaz na objekt skrývající se pod odkazem petrsAccount.

  • Od této chvíle můžeme s účtem petrsAccount manipulovat rovněž přes odkaz (proměnnou) p.

  • Což se také děje: p.transferTo(ivansAccount, 50);

Přiřazování objektových proměnných (2)

...
public static void main(String[] args) {
   Account petrsAccount = new Account();
   Account ivansAccount = new Account();
   Account p;
   petrsAccount.add(100);
   ivansAccount.add(220);
   p = petrsAccount;
   p.transferTo(ivansAccount, 50);
   // odečte se z také Petrova účtu
   petrsAccount.writeBalance();
   // vypíše 50
   ivansAccount.writeBalance();
}

Vracení odkazu na sebe (1)

Metoda může vracet odkaz na objekt, nad nímž je volána pomocí + return this;+

Příklad - upravený Account s metodou transferTo vracející odkaz na sebe

Vracení odkazu na sebe (2)

public class Account {
   private double balance;
   public void add(double amt) {
      balance += amt;
   }
   public void writeBalance() {
      System.out.println(balance);
   }
   public Account transferTo(Account whereTo, double a) {
      add(-a);
      whereTo.add(a);
      return this;
   }
}

Řetězení volání

Vracení odkazu na sebe (tj. na objekt, na němž se metoda volala) lze s výhodou využít k "řetězení" volání:

...
public static void main(String[] args) {
   Account petrsAccount = new Account();
   Account ivansAccount = new Accont();
   Account igorsAccount = new Account();
   petrsAccount.add(100);
   ivansAccount.add(100);
   igorsAccount.add(100);
   // budeme řetězit volání:
   petrsAccount
      .transferTo(ivansAccount, 50)
      .transferTo(igorsAccount, 20);
   petrsAccount.writeBalance(); // vypíše 30
   ivansAccount.writeBalance(); // vypíše 150
   igorsAccount.writeBalance(); // vypíše 120
}