Konstruktory
Wiemy już, że aby utworzyć nowy obiekt należy skorzystać ze słówka kluczowego new. Na tej lekcji kursu dowiemy się jak tworzyć obiekty w taki sposób, aby na przykład od razu miał zainicjowane pola jakimiś podanymi przez nas danymi. Do tej pory robiliśmy to poprzez utworzenie nowego obiektu i po prostu nadanie wartości zmiennym, które przechowywał. Konstruktory uproszczają to w znacznym stopniu, a dodatkowo mogą w trakcie wykonania wywoływać inne metody. Weźmy jako przykład klasę Punkt.
class Punkt {
int x;
int y;
}
To jej podstawowa wersja i zawiera tylko dwa pola typu int. Aby je zainicjować korzystaliśmy z takiej serii instrukcji:
Punkt punkt = new Punkt();
punkt.x = 3;
punkt.y = 5;
Oczywiście byłoby strasznie niewygodnie, gdyby nie dało się tego zrobić prościej. W tym celu można użyć konstruktora - specjalnej metody, która pomaga przy tworzeniu obiektów. Konstruktory zawierają kilka podstawowych cech:
- Nie określa się ich zwracanego typu
- Ich nazwa jest identyczna z nazwą klasy, w której występują
Schematycznie wygląda to tak:
class Nazwa_Klasy{
specyfikator_dostepu Nazwa_Klasy(parametry_konstruktora){
inicjowanie pól i wywołanie metod
}
dalsza część kodu, metody itp
}
Oczywiście ich umiejscowienie nie ma znaczenia. konstruktory mogą znajdować się zarówno na początku, jak i na końcu kodu. Konstruktory mogą wywoływać dowolne metody znajdujące się w klasie. Przykładowo "wzbogacona" klasa Punkt mogłaby wyglądać tak:
class Punkt {
int x;
int y;
public Punkt(int a, int b){
x = a;
y = b;
}
}
Widzimy tutaj standardowo dwa pola typu int oraz konstruktor przyjmujący dwa parametry typu int, które służą do inicjowania pól. Możemy go teraz wykorzystać w klasie testowej:
public class Test{
public static void main(String args[]){
Punkt punkt = new Punkt(10, 20);
System.out.println("Współrzędne to: ");
System.out.println("x: "+punkt.x);
System.out.println("y: "+punkt.y);
}
}
Utworzyliśmy tutaj obiekt typu Punkt przy pomocy konstruktora przyjmującego dwa argumenty 10 i 20. Jak widać odpowiednie pola zostały zainicjowane, a konstruktor pozwolił nam zaoszczędzić 2 linijki kodu i utworzyć obiekt w wygodniejszy sposób.
Konstruktorów w obrębie jednej klasy może być oczywiście wiele, czyli można je przeciążać podobnie jak zwykłe metody. Rozbudujmy klasę Punkt:
public class Punkt {
int x;
int y;
public Punkt(){ }
public Punkt(int a, int b){
x = a;
y = b;
}
public Punkt(Punkt pkt){
x = pkt.x;
y = pkt.y;
}
}
Powyżej widzimy dodatkowy konstruktor, który nazywać będziemy konstruktorem kopiującym. Jako jego argument możemy przekazać wcześniej utworzony obiekt typu Punkt, a na jego podstawie utworzony zostanie nowy obiekt z polami ustawionymi na takie same wartości.
Ważnym dopowiedzeniem do powyższego przykładu jest to, że jeżeli w klasie nie stworzyliśmy jawnie żadnego konstruktora to zostanie on dodany automatycznie przez kompilator. Dodatkowo pierwszą instrukcją jaka wykona się przy wywołaniu konstruktora z jakimkolwiek parametrem będzie wywołanie konstruktora bezargumentowego klasy nadrzędnej - czyli w przypadku braku dziedziczenia (o którym nieco później) to zostanie wywołany konstruktor klasy Object. . Brzmi to może na razie dosyć zawile, ale wygląda to tak:
//przykład1
public class A {
}
//to tak naprawdę:
public class A {
public A() {
super();
}
}
//przykład2
public class A {
public A() { }
}
//to to samo co:
public class A {
public A() {
super();
}
}
//przykład 3
public class A {
public A(int a) { }
}
//to to samo co:
public class A {
public A(int a) {
super();
}
}
Na razie nie trzeba sobie tym specjalnie zaprzątać głowy, a o instrukcji super() dowiemy się już niebawem, jednak trzeba to zapamiętać, ponieważ jest to istotny element dziedziczenia i w przypadku nawet niezbyt skomplikowanej hierarchii klas dziedziczących po sobie może się stać coś nieoczekiwanego (jedna z zagadek w JavaTraps będzie z tym związana).
Nie jest wymagane pisanie konstruktora domyślnego bez parametrów, ale moim zdaniem "przyzwoitość", oraz wyżej wspomniana cecha wymaga jego zapisanie. Warto wyposażać nasze klasy w różne wersje konstruktorów, aby dać użytkownikowi więcej możliwości tworzenia obiektów. Na koniec wykorzystanie powyższej, udoskonalonej klasy Punkt:
public class Firma{
public static void main(String args[]){
Punkt punkt1 = new Punkt(10, 20);
System.out.println("Współrzędne 1 to: ");
System.out.println("x1: "+punkt1.x);
System.out.println("y2: "+punkt1.y);
Punkt punkt2 = new Punkt(punkt1);
System.out.println("Współrzędne 2 to: ");
System.out.println("x2: "+punkt2.x);
System.out.println("y2: "+punkt2.y);
}
}
Początek jest identyczny jak poprzednio. Później, do utworzenia drugiego obiektu punkt2, wykorzystujemy drugi konstruktor, który przyjmuje jako parametr inny obiekt tej klasy.
Dyskusja i komentarze
Masz pytania do tego wpisu? Może chcesz się podzielić spostrzeżeniami? Zapraszamy dyskusji na naszej grupie na Facebooku.
Poniżej znajdziesz archiwalne wpisy z czasów, gdy strona była jeszcze hobbystycznym blogiem.
Konrad
Trochę zawiły ten kurs i niektóre rzeczy trzeba czytać po kilka razy ;) ale jak na razie wszystko mi jakoś wychodzi. A tak na poważnie to mógłbyś pisać bardziej ludzkim językiem (klasy,metody,konstruktory...) idzie się pogubić. Pozdrawiam
Amman
Nie narzekaj, póki co to najbardziej "ludzki" kurs Javy jaki spotkałem... Jak widziałem teksty typu: "Paradygmat programowania zorientowanego obiektowo w Javie opiera się na pojęciu klasy, które w sposób istotny wzbogaca strukturę modularną i semantyczną programów. " w programowaniu "dla zielonych" to myślałem że to ze mną jest już coś nie tak xD
Michał
@up Mooocne! Uwielbiam takie książki :D
Krzysiek
Konrad nie narzekaj, mi też wydawało się że ta teoria jest zbytnio zagmatwana, takie masło maślane, ale teraz jak przeanalizowałem sobie pare działów bogatych w przykłady ze stron anglojęzycznych i powróciłem tutaj to wiem, że prościej tłumaczyć się tego już nie da!!! Niby coś jest prostą sprawą, ale jak chce się to coś wytłumaczyć to aniuansów powstaje od cholery. Ten kurs jest poprostu genialny w swojej prostocie, dla mnie stanowi on teraz bardzo dobry utrwalacz, myślę, że jak byłby bogatszy w przykłady byłby już cudem:)
Mag
Ja wychodzę z założenia, że jak czegoś na razie nie rozumiem to brnę dalej kolejne lekcje i mi się rozjaśni. Puki co się sprawdza ;)
Kroot
Kondrad, autor nie powymyslal tych nazw, taka terminologia. Jak inaczej mialby te rzeczy nazywac? Jedyne do czego moznaby sie troszke czasami przyczepic to skladnia zdan. Czasami trzeba sie naglowic o co chodzi autorowi, ale zazwyczaj idzie sie domyslec po przykladach kodu. No ale piszac tyle tekstu, byc moze przy zmeczeniu to jest zrozumiale. No ale jak by nie bylo, jest to poki co najlepszy polki kurs Javy w sieci.
kamiler65
Czemu mi nie działa? public class Obiekt { public static void main(String args[]){ Punkt punkt = new Punkt(); punkt.x=100; punkt.y=100; System.out.println("punkt.x="+punkt.x); System.out.println("punkt.y="+punkt.y); } }
Slawek
a utworzyłeś klasę Punkt?
GJeszka
<blockquote> <a href="#comment-550" rel="nofollow"> <strong><em>Amman:</em></strong> </a> Nie narzekaj, póki co to najbardziej „ludzki” kurs Javy jaki spotkałem… Jak widziałem teksty typu: „Paradygmat programowania zorientowanego obiektowo w Javie opiera się na pojęciu klasy, które w sposób istotny wzbogaca strukturę modularną i semantyczną programów. ” w programowaniu „dla zielonych” to myślałem że to ze mną jest już coś nie tak xD </blockquote> Są książki pisane z przesłaniem "O jaki ja jestem mądry" i takie "Zobacz jakie to proste". Niestety trafiłeś widocznie na typ pierwszy ;)
Arkadiusz
<blockquote> <a href="#comment-493" rel="nofollow"> <strong><em>Konrad:</em></strong> </a> Trochę zawiły ten kurs i niektóre rzeczy trzeba czytać po kilka razy ale jak na razie wszystko mi jakoś wychodzi. A tak na poważnie to mógłbyś pisać bardziej ludzkim językiem (klasy,metody,konstruktory…) idzie się pogubić. Pozdrawiam </blockquote> Czytać czytać, i jeszcze raz czytać, aż się zrozumie przynajmniej ja jestem takiego zdania, a potem pisać pisać i jeszcze raz pisać, jak się zrozumie podstawowe mechanizmy reszta to doświadczenie.
kuoks
Jak dla mnie kurs świetny i prawdę mówiąc, pierwszy dzięki któremu zrozumiałem sens programowania obiektowego :D (ucząc się php dobre dwa lata nie mogłem za nic pojąć do czego to potrzebne)
Asia
Wysłałam maila z zapytaniem, proszę o szybką odpowiedź
mike
Mam pewien problem z drukowaniem zmiennej String, zamiast tego wyświetla się coś takiego: "Ksiazka@35150b68 Ksiazka@16334cb9 Ksiazka@456a5c7c Ksiazka@5973b262" Czy mógłby mnie ktoś nakierować co do rozwiązania tego problemu?
mike
Problem solved - po napisaniu tego komentarza mnie olśniło :)
tomek
To szkoda, że nie olśniło Cię na tyle, aby podzielić się rozwiązaniem z innymi. Nigdy nie zrozumiem takich ludzi jak Ty, którzy wolą się pochwalić, że jest po problemie zamiast opisać co było źle.
lukasz
No niestety mam wrażenie, że momentami autor bardziej próbuje wytłumaczyć coś sobie niż czytelnikowi. Proszę nie wyjaśniać jednego terminu innymi terminami, tylko tak może bardziej po ludzku :) Mam też jak dotąd wrażenie, że te obiekty tylko komplikują sprawę niż w czymkolwiek pomagają. Brakuje od samego początku jakiegoś przykładu, który by pokazywał, że te obiekty coś dają, ułatwiają, a nie tylko komplikują życie. Wszystko to co było do tej pory przedstawione byloby prostsze gdyby to napisać linearnie. Przepraszam, że tak krytycznie, ogólnie ten kurs mi się podoba, ale już powoli zaczynam odpadać.
Slawek
Nie twierdzę, że kurs jest najlepszy na świecie i że każdy go zrozumie - warto zawsze sięgnąć po książkę. Niestety na podstawie stwierdzeń "ja tego nie rozumiem" nie jestem w stanie nic poprawić. Krytyka jest ok, bo to dzięki wam dużo rzeczy zostało poprawione, tylko konkretniej proszę - których terminów nie było, co jest niejasne :) Czy obiekty w czymś pomagają to raczej trzeba mieć wcześniej z językiem strukturalnym do czynienia - na początku rzeczywiście może wydawać się to dziwne. Na tym etapie nie da się tego wyjaśnić, bo musiałbym napisać o dziedziczeniu, które jest w dalszych lekcjach.
Krzysiek
"Mam też jak dotąd wrażenie, że te obiekty tylko komplikują sprawę niż w czymkolwiek pomagają" - Obiekty, klasy, ich zagnieżdzenia, dziedziczenia itd., stwarzają możliwości tworzenia rozbudowanych programów do pobierania wielu danych od użytkowników i ich przetwarzania. Wiem, że jest to irytujące kiedy po napisaniu kodu na 5 stron notatnika w pełnym ekranie konsola wyświetli nam tylko x = 100. Po cholere było tyle tego pisać skoro można było zrobić to za pomocą jednej zmiennej, ale czy za pomocą tej jednej zmiennej powstawałyby dzisiaj te wszystkie cuda softwareowe?
lukasz
Tylko piszę, co myślę. I tak zaskoczę o co w tym wszystkich chodzi, ale po prostu zżymam się, gdy widzę, że ktoś coś wyjaśnia używając pojęć o których musi być prawie pewien, że ktoś kto czyta ten tutorial ich nie rozumie. Znalazlem jeden tutorial na youtube gdzie jakaś hiszpanka wszystko jasno tłumaczy, jak krowie na rowie, czyli jednak jest to możliwe. Ad/Krzysiek - doskonale sobie wyobrażam, że obiektowość czemuś ważnemu służy, skoro przetrwala. Chodzi mi tylko o to, że przykłady, które się stosouje w takim tutorialu powinny jakoś pokazywać korzyść ze stosowania obiektów, a nie tylko nieczemu nieslużącą komplikację :) Po co mam pisać Punkt punkt = new Punkt (), skoro mogę napiać x=1 (pomijam fakt, że byłoby przejrzyściej, gdyby pisać Punkt kropka = new Punkt () :)
Slawek
Punkt to dwie współrzędne, więc nie możesz napisać x=1. Zakładam, że każdy kto się zabiera za ten kurs miał już geometrię jako taką :P Dzięki za uwagi, jednak jeszcze raz proszę Cię o wskazanie co wcześniej nie było wytłumaczone, bo tak nie jestem w stanie niczego poprawić :)
lukasz
Bardziej chodzilo mi o to, że lepiej byłoby tłumaczyć na zasadzie Pies burek = new Pies () niż Pies pies = new Pies (), co brzmi dla niewtajemniczonego jak maslo maslane. (I tak, wiem, że wielkość liter ma znaczenie) Tutaj całkiem przejrzyście kobieta tlumaczy, jak przedszkolakom; tyle trzeba wypić porządną kawę, żeby nie uśpila tonem glosu: http://www.youtube.com/watch?v=lm9Hh9lApJA&feature=relmfu Wyjaśnienie nie polega na tym, żeby powiedzieć, na czymś coś polega, tylko żeby sprawić, żeby ktoś inny był w stanie powiedzieć, na czym coś polega. Dobrze próbować wejść w umysł ucznia ;)
Zbyszek
Mam pytanie: dlaczego raz piszemy main(String[] args) a raz main(String args[])?
TeWu
Te dwa zapisy są równoważne - autor kursu powinien nie komplikować rzeczy za bardzo i konsekwentnie używać jednej wersji. Wybierz sobie która wersja ci się bardziej podoba i tak pisz - ja lubię "String[] args" bo czytam to "tablica stringów o nazwie args", ale druga wersja oznacza to samo, tylko inny sposób na napisanie tego samego. Trochę jak "Ala ma kota" i "Ala kota ma" w języku polskim. Dwa razy to samo, chociaż "Ala ma kota" brzmi jakoś lepiej.
Witek
Witam To nie ma znaczenia czy napiszesz tak: main(String[] args) czy tak main(String args[]) Osobiście wolę pisać tą drugą wersję ponieważ tak się przyzwyczaiłem i tak pisze, uważam, że jest to po prostu rzecz gustu i przyzwyczajenia. Obie wersje są poprawne i to ty decydujesz jaką wersję wybierzesz. Pozdrawiam.
Tomek
Genialny kurs. Pozdrawiam autora. Jeszcze by sie kurs pisania na Adroida przydal w tak doskonałej konwencji.
velmafia
@autor: w 7 listingu (bloku code) html zignorował Ci tagi "strong", przez co kod wygląda głupio, jak je usuniesz i zostawisz tylko //przyklad1 itp będzie lepiej i czytelniej. swoją drogą znam C++ i to jak działa dziedziczenie (i resztę otoczki związanej z programowaniem obiektowym) ale nie wiem co tym listingiem chciałeś przekazać, IMO lepiej było by bez niego (przynajmniej na tym poziomie nauki). @wszyscy co marudzą że autor używa trudnych wyrazów: ludzie, jeden kurs nie zrobi z was programistów, ten kurs jest dobry jako wprowadzenie, ale dopóki nie nauczycie się googlować i samemu wyjaśniać to czego nie rozumiecie, to będziecie dupą a nie programistą. chcesz się nauczyć programować? to musisz poświęcić trochę czasu, nikt za Ciebie tego nie zrobi. ten kurs jest dobry (IMO), ale to ty chcesz się nauczyć programować, autor może Ci co najwyżej pomóc.
Kamil
A po co w klasie Punkt autor utworzył konstruktor Punkt, którego argumentem jest... obiekt klasy Punkt? To mi przypomina węża zjadającego swój własny ogon. Wszystko z tego kursu póki co zrozumiałem, ale sensu tego zapisu nie kumam...
Sławek Ludwiczak
Jest to konstruktor kopiujący - jeśli potrzebujesz nowej, ale identycznej instancji takiego samego obiektu, to wystarczy, że właśnie jego przekażesz - nie trzeba się odwoływać do pojedynczych pól. To jest oczywiście najprostszy przypadek - w innych jest to dużo bardziej użyteczne. W skrócie zamiast robić: <pre> Punkt pkt = new Punkt(2, 2); Punkt pkt2 = new Punkt(pkt.x, pkt.y); </pre> robimy właśnie <pre> Punkt pkt = new Punkt(2, 2); Punkt pkt2 = new Punkt(pkt); </pre> Dodatkowo nie jest to powiedziane, ale można w tym miejscu wykorzystać inny wzorzec - konstruktor teleskopowy: <pre> public Punkt(Punkt pkt){ this(pkt.x, pkt.y); } </pre>
Asr
one działają jak metody przeciązone te konstruktory zalezy jakie arg odpala się kokretny kons ;]
Rafał
Wiele komentarzy, ale niezauważona przeszła drobna nieścisłość. Zacytuję: "Na koniec wykorzystanie powyższej, udoskonalonej klasy Punkt: public class Firma{ ... " To jak sądzę wynika ze skopiowania części kodu z innego przykładu (mowa w opisie o klasie Punkt a definiowana jest klasa Firma. Co prawda będzie działać, ale to dla porządku.
jwyerzy
Tu wszystko jest OK, mowi się o wykorzystaniu klasy Punkt, a nie o napisaniu klasy Punkt. Klasa Punkt została zdefiniowana wyżej z przeciążonym konstruktorem i tutaj ( w klasie testującej o nazwie Firma) zostało zastosowane: Punkt punkt1 = new Punkt(10, 20); ... Punkt punkt2 = new Punkt(punkt1); ...
cimber
Kurs świetny. Zawsze miałem niechęć do javy, a ten kurs udowadnia że można się jej uczy bez obrzydzenia. Trzymam kciuki za dalszy rozwój portalu!
adi191pls
Kurs świetny. Jednak na tej lekcji zatrzymałem się naprawdę na dłużej. Po 40 przeanalizowaniu przykładów i googlowaniu dalej nie rozumiem, do jakich celów i jakie argumenty używać w konstruktorach. Jedyne, co na razie zrozumiałem, to nadawanie wartości zmiennym za pomocą innych zmiennych. Jednak mam problem ze zrozumieniem tego typu konstruktorów: public Punkt(Punkt pkt){ x = pkt.x; y = pkt.y; Można to jakoś łopatologiczne wyjaśnić?
Faraen
Kurs świetny przejrzysty, i jak nie rozumie się terminologii to wystarczy na chwile cofnąć się na początek kursu dla przypomnienia :). @adi191pls Prosto mówiąc ten konstruktor przyjmuje jako argument obiekt, czyli np. jakąś klasę, w przykładzie zobaczysz że konstruktorowi temu został przekazany argument punkt1. punkt1 został stworzony przy pomocy konstruktora Punkt(int a, int b) i nadano wartość jego argumentom 10 i 20, więc kiedy przekazano konstruktorowi Punkt(Punkt pkt) obiekt punkt1 to mógł on wyciągnąć z niego wartości jego argumentów, właśnie przez przypisanie x = pkt.x (czyli x przyjmuje wartość punkt1.x (czyli zmiennej x w obiekcie punkt1)) :) mam nadzieje że to ci coś rozjaśni, ale po 3 miesiącach mogłeś pewnie już sam znaleźć odpowiedź :P.
Ciekawa
//przykład1 public class A { } //to tak naprawdę: public class A { public A() { super(); } }Dlaczego jest to super();? co ono robi? jakie ma zastosowanie i co jest do niego przekazywane?