Zamknij komunikat

Nowy Office 2013
Do góry Skomentuj

07. Tworzenie oraz inicjalizacja obiektów

07. Tworzenie oraz inicjalizacja obiektów

Daniel Celeda
10 stycznia 2006
252 745
Odsłony
Daniel Celeda
10 stycznia 2006
252 745
Odsłony

W poprzednim artykule stworzyliśmy nasz pierwszy obiekt. Dzisiaj dowiemy się na czym polega mechanizm tworzenia obiektów i jak używać konstruktorów (specjalnych metod przeznaczonych do tego celu).

Definiowanie konstruktorów

Przypomnijmy sobie program z poprzedniego artykułu.

class Echo
{
    string napis;
    public void WczytajNapis()
    {
        System.Console.WriteLine("Podaj napis.");
        napis = System.Console.ReadLine();
    }
    public void Napisz()
    {
        System.Console.Write("Napisałeś: ");
        System.Console.WriteLine(napis);
    }
}

class
KlasaGlowna
{
    static void Main()
    {
        Echo obiektEcho = new Echo();
        obiektEcho.WczytajNapis();
        obiektEcho.Napisz();
    }
}

Przypominam, że teksty umieszczone w cudzysłowach to łańcuchy znakowe. Instrukcja „new Echo()” nakazuje stworzenie nowego obiektu. „Echo()” to konstruktor klasy, której instancję chcemy stworzyć. No tak, ale przecież w klasie „Echo" nie mamy zdefiniowanego żadnego konstruktora. Nie jest to prawdą, ponieważ w każdej klasie jest zdefiniowany domyślny konstruktor, który możemy zastąpić własnym. Co więcej, możemy w jednej klasie stworzyć kilka konstruktorów i używać ich w zależności od potrzeb.
Do czego potrzebne są nam konstruktory? Nie wystarczyłoby same słówko „new”?
Dzięki konstruktorowi, możemy podczas jego użycia od razu przypisać wartości zmiennym. Przypatrzmy się poniższemu przykładowi.

class Echo
{
    string napis;
    public Echo(string nowyNapis)
    {
        napis = nowyNapis;
    }

    public void Napisz()
    {
        System.Console.Write("Napisałeś: ");
        System.Console.WriteLine(napis);
    }
}
class
KlasaGlowna
{
    static void Main()
    {
        Echo obiektEcho = new Echo("Napis podany w konstruktorze");
        obiektEcho.Napisz();
        System.Console.ReadLine();
    }
}

Konstruktor zdefiniowany jest tutaj:

public Echo(string nowyNapis)
{
    napis = nowyNapis;
}

Definicję konstruktora powinno poprzedzać słówko „public”, ponieważ konstruktor będzie używany wewnątrz innych klas, które będą chciały powoływać do życia obiekty klasy „Echo”. Istnieją sytuacje, w których należy zdefiniować prywatny konstruktor, jednak nas one na razie nie dotyczą J Parametr jaki przyjmuje konstruktor to „nowyNapis”. Jest to parametr typu „string”, a więc tekstowy. W ciele konstruktora, zmiennej „napis” przypisujemy wartość podaną w parametrze.

Zobaczmy teraz jak będzie wyglądał wynik działania programu z domyślnym konstruktorem.

class Echo
{
    string napis;
    public void Napisz()
    {
        System.Console.WriteLine(napis);
        System.Console.ReadLine();
    }
}
class
KlasaGlowna
{
    static void Main()
    {
        Echo obiektEcho = new Echo();
        obiektEcho.Napisz();
    }
}

Nic nie pojawiło się na ekranie, ponieważ nie wpisujemy żadnej wartości do zmiennej “napis”. Domyślną wartością dla zmiennej typu string jest pusty tekst, a więc jeśli chcemy użyć zmiennej tekstowej, do której wcześniej nic nie „włożyliśmy” wynik będzie taki, jakbyśmy wykonali wcześniej instrukcję:

napis = "";

Spójrzmy na program z konstruktorem zdefiniowanym przez nas, ale będącym identycznym jak domyślny.

class Echo{
    string napis;
    public Echo()
    {
    }

    public void Napisz()
    {
        System.Console.WriteLine(napis);
        System.Console.ReadLine();
    }
}
class
KlasaGlowna
{
    static void Main()
    {
        Echo obiektEcho = new Echo();
        obiektEcho.Napisz();
    }
}

Wynik nie będzie się różnił od programu z konstruktorem domyślnym.
Napiszmy teraz program z kilkoma konstruktorami.

class Echo
{
    string napis;
    string napis2;

    public Echo()
    {
    }

    public Echo(string parametr)
    {
        napis = parametr;
    }

    public Echo(string parametr1, string parametr2)
    {
        napis = parametr1;
        napis2 = parametr2;
    }

    public void Napisz()
    {
        System.Console.WriteLine(napis);
        System.Console.WriteLine(napis2);
    }
}
class
KlasaGlowna
{
    static void Main()
    {
        Echo obiekt1 = new Echo();
        Echo obiekt2 = new Echo("Konstruktor z jednym parametrem.");
        Echo obiekt3 = new Echo("Konstruktor z dwoma parametrami.", "Drugi parametr.");
        obiekt1.Napisz();
        obiekt2.Napisz();
        obiekt3.Napisz();
        System.Console.ReadLine();
    }
}
 

Stworzyliśmy 3 konstruktory, pierwszy bezparametrowy (zmienne “napis” oraz “napis2” otrzymują domyślne puste wartości), drugi z jednym parametrem przypisującym wartość zmiennej „napis” oraz trzeci, który przypisuje wartości obydwu zmiennym. W metodzie „Main()” klasy „KlasaGlowna” tworzymy trzy obiekty klasy „Echo”, wywołując stworzone przez nas konstruktory. Wynik działania programu to wypisane wartości znajdujące się w zmiennych „napis” oraz „napis2” każdego z obiektów.

Ważną sprawą jest, aby deklaracje naszych konstruktorów były unikalne, a więc jeśli mamy 3 różne konstruktory to wywołując je powinno być jednoznacznie wiadomo, o który chodzi. Aby konstruktory odróżniały się muszą mieć różna liczbę parametrów bądź różny ich typ (np. jeden z parametrem typu „string”, a drugi z parametrem typu „int”). W naszym przykładzie konstruktory różnią się ilością otrzymywanych parametrów. Wywołując konstruktor z jednym parametrem typu „string”, jednoznacznie wiadomo, że chodzi o drugi konstruktor.

Inicjalizacja składowych

 Jeśli nasz klasa jest rozbudowana i ma wiele zmiennych oraz konstruktorów to może się zdarzyć, że w każdym z nich będziemy musieli przypisywać wartości zmiennym. Dużo nadmiarowej pracy – dublowanie się kodu. Możemy temu zapobiec na kilka sposobów.

Wywołanie jednego konstruktora poprzez drugi

 Aby uzyskać taki efekt musimy użyć słówka „this”.

class Echo
{
    string napis;
    string napis2;

    public Echo(string parametr)
    {
        napis = parametr;
    }

    public Echo(string parametr1, string parametr2) : this(parametr1)
    {
        napis2 = parametr2;
    }

    public void Napisz()
    {
        System.Console.WriteLine(napis);
        System.Console.WriteLine(napis2);
    }
}
class
KlasaGlowna
{
    static void Main()
    {
        Echo obiekt = new Echo("Pierwszy parametr.", "Drugi parametr.");
        obiekt.Napisz();
        System.Console.ReadLine();
    }
}

W tym przykładzie mamy dwa konstruktory, z jednym oraz z dwoma parametrami. W definicji drugiego wywołujemy pierwszy poprzez słówko „this” oraz przekazujemy do pierwszego pierwszy parametr. W linijce:

Echo obiekt = new Echo("Pierwszy parametr.", "Drugi parametr.");

wywołujemy drugi konstruktor (dwa parametry), ten natomiast wywołuje pierwszy przekazując mu wartość „Pierwszy parametr.". Tak więc wartość zmiennej „napis” jest ustalana w pierwszym konstruktorze, który został wywołany przez drugi, natomiast wartość zmiennej „napis2” jest przypisywana w drugim konstruktorze.

Inicjalizacja w dodatkowej metodzie

Polega ona na przypisaniu wartości do zmiennych w dodatkowej (lub w kilku) metodzie.

class Echo
{
    string napis;
    string napis2;

    public Echo(string parametr1, string parametr2)
    {
        PrzypiszWartosci(parametr1, parametr2);
    }
    public void PrzypiszWartosci(string parametr1, string parametr2)
    {
        napis = parametr1;
        napis2 = parametr2;
    }

    public void Napisz()
    {
        System.Console.WriteLine(napis);
        System.Console.WriteLine(napis2);
    }
}
class
KlasaGlowna
{
    static void Main()
    {
        Echo obiekt = new Echo("Pierwszy parametr.", "Drugi parametr.");
        obiekt.Napisz();
        System.Console.ReadLine();
    }
}

Inicjalizacja na etapie deklaracji

W C# możemy przypisywać wartości do zmiennych już na etapie ich deklarowania.

class Echo
{
    string napis = "Pierwszy parametr.";
    string napis2 = "Drugi parametr.";

    public void Napisz()
    {
        System.Console.WriteLine(napis);
        System.Console.WriteLine(napis2);
    }
}
class
KlasaGlowna
{
    static void Main()
    {
        Echo obiekt = new Echo();
        obiekt.Napisz();
        System.Console.ReadLine();
    }
}

Ćwiczenie

Stwórz klasę „Czlowiek” zawierającą zmienne:

  • imię typu string,
  • nazwisko typu string,
  • wiek typu int.

Zdefiniuj konstruktor dla tej klasy, który na podstawie otrzymanych parametrów zainicjalizuje jego zmienne.

Stwórz klasę główną aplikacji, w jej metodzie „Main()” stwórz obiekt klasy „Czlowiek” przekazując do konstruktora odpowiednie wartości. Wypisz na ekranie zawartość zmiennych opisujących nowopowstały obiekt (imię, nazwisko oraz wiek).

Rozwiązanie:


class Czlowiek
{
    string imie;
    string nazwisko;
    int wiek;

    public Czlowiek(string noweImie, string noweNazwisko, int nowyWiek)
    {
        imie = noweImie;
        nazwisko = noweNazwisko;
        wiek = nowyWiek;
    }

     public void WypiszDane()
    {
        System.Console.WriteLine("Imię: " + imie);
        System.Console.WriteLine("Nazwisko: " + nazwisko);
        System.Console.WriteLine("Wiek: " + wiek);
    }
}

class KlasaGlowna
{
    static void Main()
    {
        Czlowiek jan = new Czlowiek("Janusz", "Kowalski", 20);
        jan.WypiszDane();
        System.Console.ReadLine();
    }
}

Zobacz również

Komentarze

Napisałeś: Napis podany w konstruktorze Takie jest rozwiazanie ale dlaczego tak to dziala to nie mam pojecia. Jak dotad wszystko bylo dla mnie bardzo jasne i klarowne ale pojecie konstruktora troche mnie przygniotlo, bo nie widze zadnego sensu w tej konstrukcji. Zwlaszcza tekstu w metodzie main (Napis podany w konstruktorze)obok stworzonego obiektu Echo-jak to sie ma do konstruktora?
Kastor25, 22 czerwca 2006, 13:18
OK juz mam:) Echo obiektEcho = new Echo("Napis podany w konstruktorze "); Ta linia odnosi sie bezposrednio do: public Echo(string nowyNapis) Poniewaz string jest parametrem tekstowym automatycznie nowyNapis=Napis; podany w konstruktorze. wtedy napis = nowyNapis; a co za tym idzie tekst wskakuje do pamieci pod nazwa konstruktora string napis; Cala operacja sprowadza sie do przyporzadkowania tekstu do slowa napis ktore jest wykorzystane w dalszej czesci kodu. Troche to zawiklane ale jesli sie myle to prosze o sprostowanie;)
Kastor25, 22 czerwca 2006, 13:47
KOREKTA: Trzecia linia --automatycznie nowyNapis="Napis podany w konstruktorze"
Kastor25, 22 czerwca 2006, 13:51
Poradnik jest spoksik, przydaje się:) chociaz mozna sie zamotac
Arcdoes, 11 lipca 2006, 14:58
cytat: Definicję konstruktora powinno poprzedzać słówko „public”, ponieważ konstruktor będzie używany wewnątrz innych klas, które będą chciały powoływać do życia obiekty klasy „Echo”. Istnieją sytuacje, w których należy zdefiniować prywatny konstruktor, jednak nas one na razie nie dotyczą koniec cytatu. A kiedy będą nas dotyczyć? Może warto by o tym wspomnieć. Poza tym określenie "Dzięki konstruktorowi, możemy podczas jego użycia od razu przypisać wartości zmiennym." nie jest najszczęśliwszym określeniem konstruktora.
bartek, 21 sierpnia 2006, 16:16
bartek jak się nie podoba to sam napisz lepszy kurs. Ten jest dla początkujących i takie określenie na razie wystarcza, później odkryją inne zastosowania konstruktora. A jak chcesz mieć wszystko dokladnie to proszę bardzo: http://www.microsoft.com/poland/developer/press/visual_csharp.mspx. Ale to kosztuje, a za darmo nic lepszego od tego kursu nie znajdziesz, a jeszcze narzekasz, że ktoś poświęca swój czas (=pieniądze) żeby Cię czegoś nauczyć...
Dominik, 23 lipca 2007, 12:22
Nie ma co narzekać trzeba grzecznie podziekować za kurs bo jest za co !!!
ketchOOp, 8 sierpnia 2007, 10:12
Warto by wspomnieć że w części na temat "Inicjalizacja w dodatkowej metodzie", zmienne parametr1 i parametr2 w konstruktorze: public Echo(string parametr1, string parametr2) i w zwykłej metodzie: public void PrzypiszWartosci(string parametr1, string parametr2) są faktycznie widziane przez program jako zupełnie różne zmienne, parametry które należą do danej metody. Czyli jeśli deklaracja metody pomocniczej wyglądałaby: public void PrzypiszWartosci(string parametr3, string parametr4) to też powinno działać, bo to są lokalne zmienne, przynależne do metody. przynajmniej tak było w C++ :/. To żeby ludzie nie mysleli że w takich przypadkach trzeba te zmienne nazywać tak samo jak w koństruktorze ;P
OwcA, 3 września 2007, 23:57
poprostu- od paru przykladów autor stara sie wyjasnić że można w różnych momentach i na różne sposoby przypisać wartość zmiennymi tyle
j, 8 października 2007, 13:20
Kurs spoko tylko nie chce mi się pokazać rozwiązanie
Quavitor, 14 kwietnia 2008, 19:46
Rozwiązanie pokaże się jak skorzystasz z Internet Explorera.
Tomek, 19 maja 2008, 20:24
ale co to w ogole jest ten konstruktor? bo czytam i cos nie moge zalapac
ja, 17 sierpnia 2008, 16:36
Do konstruktora przypisujesz jakieś wartości żeby przy użyciu okiektu nie pojawiły się dziwne rzeczy "śmieci " . Chodzi o to że jeśli masz klasę która przykładowo dodaje ułamki, to chciałbyś najpierw wczytać wartośc dla tych ułamków z klawiatury a pózniej dodać. Konstruktor jest Ci potrzebny po to aby na wszelki wypadek na początu przy użyciu nie dostały się tam przypadkowe wartości, np. 1/0 czy 2/0 dzielenie przez zero. Wtedy możesz użyć konstruktora aby zawsze przy wywołaniu w mianowniku było 1. Wtedy jesteś na 100% pewny(a), że nic złego się nie stanie i program będzie działał dobrze.

EnD-RiU, 7 października 2008, 13:51
Mam tylko mały problem bo w nie chce mi się wyświetlić rozwiązanie na stronie. To wina strony czy może ustawień przeglądarki?

PD, 13 października 2008, 16:38
w jaki sposób drugi konstruktor odnosi się do pierwszego skoro w drugim jest napisane - [color=blue">this[/color">(parametr1).

 
nie powinno być - [color=blue">this[/color">(parametr)?

 

ren, 21 października 2008, 17:28
super prosto przejrzyście
duch, 16 listopada 2008, 21:54
Powinnienes zaznaczyc, ze ten przyklad jest przytoczony tylko po to aby poznac rozne sposoby przypisywania i ewentualnie mozliwosc wywolania jednego konstruktora w drugim. Wiadomo, ze aby wyswietlic dwa proste napisy nikt nie bedzie tworzyl dwoch konstruktorow z ktorych kazdy bedzie przypisywal inny string innej zmiennej. Warto zawsze dodac jak zrobic dana czynnosc najlatwiej, mimo, ze nie samo wyswietlenie napisow jest w tym przykladzie istotne. Takie przyklady wprowadzaja zamet u poczatkujacych programistow. Mysla.... "Nie da sie osiagnac tego samego efektu w latwiejszy sposob? "

ziomek, 8 grudnia 2008, 21:16
bardzo fajny i przydatny kurs :) z początku wydawał mi się on trochę dziwny, gdyż przykłady były zapisane w postaci poleceń po polsku (jestem przyzwyczajony do normalnego kodu), aczkolwiek później było już znacznie lepiej, bo były zapisane już właściwe kody ;">
na prawdę można się z tego wiele nauczyć
i do praktykujących:
nie wiem czy ktoś dał link do Visual C# Express 2008 bo nie sposób przeczytać wszystkich komentarzy, ale
http://www.microsoft.com/express/download/

Zhipes, 13 grudnia 2008, 12:46
witam wszystkich.
na początku wielkie dzięki za napisanie tutoriala, gdyby nie on, to pewnie rzuciłbym studia uznając pozyskanie umiejętności z programowania za mission imposible. a teraz przejdę do rzeczy:
 
nie wiem czy dobrze rozumiem jeszcze pojęcia klas i obiektów. Jesteśmy w stanie, napisać program przedstawiony w tym rozdziale w jednej klasie, prawda? ale dla potrzeb tutoriala, stworzone zostało rozbicie na dwie osobne klasy, dobrze rozumiem?
 
Dziękuję za pomoc i proszę o wyrozumiałość, mam masę pytań ciągle, spróbuje je dopiero zadać po głębokiej analizie tutoriala, żeby nie zanieczyszczać przejrzystości komentarzy. Niestety nie ma mi kto pomóc w tej dziedzinie, że tak się wyrażę "stacjonarnie".
 
pozdrawiam
adrian

Aldczak89, 13 stycznia 2009, 21:21
Świetny kurs dzięki wielkie autorowi, do tej pory do ręki brałem 600-800stronowe książki do nauki programowania, gdzie odechciewało mi się w to bawić po przeczytaniu 80-100 stronowego wstępu, bo tak zazwyczaj mają te ksiązki. A taki wstęp paraktycznie nic nie wnosił bo się po tylu stronach dochodzi do Hell World dopiero :) a tu jest wszystko fajnie wytłumaczone na przykładach i nie musze sie przebijać przez dziesiątki stron żeby dojść do tego co mnie interesuje. Pozdrawiam

Marek, 26 marca 2009, 10:50
Gładko wchodzi. Przydała się nauka c++.
BTW: Na początek polecam C++.

carck3r, 27 marca 2009, 18:38
Prosto, przejżyście, super !!!
sebeQ, 9 listopada 2009, 19:45
nic nie dzeje sie
marek, 15 maja 2010, 15:25
Fajny tutek. Dość przejrzysty język. Super 
dmxn, 24 listopada 2010, 15:52
Kurs jest po prostu super!! Chodź miałam problemy z niektórymi rzeczami. Potem dopiero sama zaczynałam powoli wpadać co jest nie tak :) najbardziej mi coś nie chciało pójśćz tym static void Main() bo mi pokazywał tj. błąd, ale potem sobie przypomniałam, że Main a main to co innego bo wielkość liter ma znaczenie ;P i potem już mi gładko szło wszystko. Pozdrawiam
Kamila, 22 stycznia 2011, 19:43
Bardzo fajny kurs :D Szczególnie jeśli zna się już jakiś inny język, najlepiej obiektowy
M@sterUkacz, 16 lutego 2011, 15:44
Odcinek z tymi konstruktormi to jakiś belkot... nie da sie nic skumać.
bri, 23 marca 2011, 11:33
rozwiązania ćwiczeń nie działają ;/
kris, 12 września 2011, 05:12
Kurs zrozumieją tylko ci, którzy umieją myśleć. Jeżeli uważasz bri że ten kurs to jest bełkot, to według mnie powinieneś się zastanowić o czym ten kurs bełkocze. Bo czytać "szybko" to ja też potrafię.
Dawid, 30 września 2011, 00:59
Chyba mi wyszło :) Tylko wartość wiek np.33 trzeba wpisać bez cudzysłowów bo to idzie do int a nie do string. :)
raf, 23 grudnia 2011, 16:43
Mógłby ktoś wyjaśnić dlaczego w metodzie WypiszDane jest ("Imie" + imie)? Tak dziala dodawanie stringów? Że po jednym się wypisuje następny?
Radziu, 5 marca 2015, 19:27

Dodaj swój komentarz

Zasady publikacji komentarzyZasady publikacji komentarzy

Redakcja CentrumXP.pl nie odpowiada za treść komentarzy publikowanych na stronach Portalu
i zastrzega sobie prawo do usuwania wypowiedzi, które:

  • zawierają słowa wulgarne, obraźliwe, prowokujące i inne naruszające dobre obyczaje;
  • są jedynie próbami reklamowania stron internetowych (spamowanie poprzez umieszczanie linków);
  • przyczyniają się do złamania prawa bądź warunków licencyjnych oprogramowania (cracki, seriale, torrenty itp.);
  • zawierają dane osobowe, teleadresowe, adresy mailowe lub numery GG;
  • merytorycznie nie wnoszą nic do dyskusji lub nie mają związku z tematem komentowanego newsa, artykułu bądź pliku.