class Person:
# default constructor
def __init__(self, name):
self.name = name
Tomáš Pitner, Radek Ošlejšek, Marek Šabo, Jakub Čecháček pitner@muni.cz
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.
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ů
class Person:
# default constructor
def __init__(self, name):
self.name = name
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;
}
}
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");
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");
Pokud třída nemá definovaný žádný konstruktor, vytvoří se automaticky výchozí (default) konstruktor:
public Person() { }
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
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;
}
}
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;
}
}
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;
}
}
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í.
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.