Konstruktory

Konstruktory

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

  • Umožňují programátorovy ovlivnit proces vytváření objektu a zejména nastavit objektu iniciální stav (hodnoty atributů).

  • Konstruktory lze volat pouze pomocí new, nelze je volat na existujícím objektu.

Konstruktory v Pythonu a Javě

  • V Pythonu jsou to metody def init(self):

  • V Javě se jmenují přesně stejně jako jejich třída (a bez návratového typu)

  • Konstruktorů v jedné třídě může být více - musí se pak lišit počtem, evt. typem parametrů

Příklad třídy s konstruktorem v Pythonu

class Person:
	# default constructor
	def __init__(self, name):
		self.name = name

Příklad třídy s konstruktorem v Javě

Pozor, konstruktor nemá návratový typ (ani void). Vždy vrací adresu vytvořeného objektu.
public class Person {
  private String name;

  public Person(String name) {
    this.name = name;
  }
}

Rozdíly Python vs Java

Java
  • identifikátor this znamená, že se přistupuje k atributům objektu. Není nutné používat tam, kde se neshoduje jméno atributu a parametru.

  • volání: Person pepa = new Person("Pepa from Hongkong");

Python
  • identifikátor self znamená totéž, ale musí se používat vždy při přístupu k atributu nebo metodě.

  • volání: pepa = Person("Pepa from Hongkong");

Výchozí (default) konstruktor

Pokud třída nemá definovaný žádný konstruktor, vytvoří se automaticky výchozí (default) konstruktor:

public Person() { }

Vlastní konstruktor

  • Pokud je ve třídě definovaný vlastní konstruktor, pak se už výchozí (default) konstruktor nevytvoří. K dispozici je pouze onen vlastní konstruktor.

  • Cílem konstruktoru je většinou nastavit iniciální stav, zde např. jméno.

public class Person {
  private String name;

  public Person(String name) {
    this.name = name;
  }
}

Použití je pak následující:

Person jan = new Person("Jan Novak");
Person karel = new Person(); // error: no such contructor available

Více konstruktorů

  • Ve třídě lze definovat více konstruktorů. Jedná se o tzv. přetěžování (overloading).

  • Konstruktory se musí lišit signaturou, tj. počtem nebo typem vstupních argumentů tak, aby volání konstruktoru s konkrétními vstupními hodnotami bylo deterministické.

  • Přetížit lze i bezparametrický konstruktor a vrátit tak "výchozí" konstruktor do třídy s více konstuktory.

public Person() {
  private String name;

  public Person() { // default constructor is back
    name = "Default name";
  }

  public Person(String name) {
    this.name = name;
  }
}

Implementace přetížených konstruktorů

  • Pro minimalizaci duplicitního kódu a lokalizace změn se doporučuje používat vzájemné volání konstruktoru.

  • Pro volání jiného (přetíženého) konstruktoru se používá this().

  • Volání this() musí být prvním příkazem a v konstruktoru se může vyskytovat jen jednou. Tj. nelze volat více přetížených konstruktorů. Lze ale volat přetížený konstruktor, který volá jiný přetížený konstruktor.

public Person() {
  private String name;

  public Person() {
    this("Default name"); // calls an overloaded constructor
  }

  public Person(String name) {
    this.name = name;
  }
}

Jak to NEDĚLAT

Následují kód konstruktoru je syntakticky správně, ale je nesmyslný. Dokážete si zdůvodnit proč?
public Person() {
  private String name;

  public Person() {
    new Person("Default name"); // NESMYSL!
  }

  public Person(String name) {
    this.name = name;
  }
}

Pouhá deklarace proměnné

Person p;
System.out.println(p.getName());
  • Výrazný rozdíl oproti C++: v Javě vůbec nepůjde přeložit.

  • Nevytvoří žádný objekt a překladač ví, že proměnná p neukazuje nikam.

  • Tudíž veškerá volání p.getName() a podobně by byla nefunkční.

Nevytvoření objektu

  • Toto již přeložit půjde - když do odkazu přiřadím null.

  • Nicméně, co se stane, když zavolám nad odkazem null metody?

Person p = null;
System.out.println(p.getName());
  • Kód po spuštění "spadne", neboli zhavaruje, předčasně skončí.

  • Java sa snaží pád programu popsat pomocí výjimek (exceptions).

  • Výjimky mají své jméno, obvykle i určitý textový popis dokumentující příčinu havárie.

Exception in thread "main" java.lang.NullPointerException
  • Výjimky budou probírány později.