Kierujemy swoje głowy ponownie w stronę klas, jednak tym razem zajmiemy się metodą wywołującą się automatycznie podczas tworzenia obiektu. Konstruktor klasy w języku C#, dokładnie to mam na myśli. Wchodźcie!
Tweet |
KONSTRUKTOR KLASY W JĘZYKU C# TO TEŻ JEST METODA...
...tylko taka bardziej "specjalna" :). Wywołuje się ona automatycznie jeden raz, po utworzeniu obiektu za pomocą słowa kluczowego "new". Przypomnę się może:
Point point = new Point();
To jest w rzeczywistości wywołanie konstruktora na rzecz podanej klasy. Jeśli jesteśmy autorami wykorzystywanej klasy albo posiadamy do niej dostęp, mamy prawo do dodania własnego konstruktora. Temu zagadnieniu trzeba się przyjrzeć najbardziej w całym artykule.
JAK UTWORZYĆ WŁASNY KONSTRUKTOR?
Konstruktor klasy w języku C# tworzy się dokładnie tak samo jak w języku Java. Zarzucę prosty przykład:
public Point(int x, int y)
{
// instrukcje
}
Umieszczamy go wewnątrz klasy i w żadnym innym miejscu:
class Point
{
public Point(int x, int y)
{
// instrukcje
}
}
Co widzimy? Bardzo podobną postać jak w przypadku funkcji. Określamy modyfikator dostępu, nazwę która ma być TAKA SAMA jak nazwa klasy, parametry formalne które konstruktor jak najbardziej może posiadać, bloczek kodu a w środku niego instrukcje. Najczęstszym modyfikatorem dostępu z jakiego przyjdzie Wam korzystać jest "public", choć wcale tak nie musi być. A co do sposobu użycia, to na 99% przypadków przyda się do inicjowania danych składowych bądź wywoływania własnych metod dla dodatkowego przygotowania obiektu do funkcjonowania. Tu ciekawostka :O! Utworzony obiekt nie posiada w sobie żadnych zmiennych niezainicjowanych (z wyjątkiem typów referencyjnych). To znaczy, że w chwili egzekwowania tej linijki kodu:
Point point = new Point();
dane składowe przyjmują odpowiednią wartość domyślną. W naszym przypadku, pola "x" i "y" przyjmą wartość 0 (zero), gdyż to są liczby całkowite.
Jeszcze jedno! Nie sądzicie, że czegoś brakuje w nagłówku konstruktora ;)? Owszem - nie ma typu zwracanej wartości! To nie jest żaden błąd, tylko obowiązkowe pominięcie tego szczegółu. W przypadku definiowania konstruktora, nie podaje się typu zwracanej wartości, NIGDY! To stanowi jedyną różnicę w sposobie zapisu pomiędzy konstruktorem, a innymi metodami.
PRZYKŁAD KODU ŹRÓDŁOWEGO
Aby udowodnić wszystkim, że konstruktor klasy w języku C# rzeczywiście wywołuje się natychmiast w trakcie tworzenia obiektu, wprowadzam wywołanie funkcji "Console.WriteLine" do niego, a w funkcji uruchomieniowej "Main", definiowanie obiektu klasy:
KLASA "POINT"
using System;
class Point
{
private int x, y;
public Point(int px, int py)
{
x = px;
y = py;
Console.WriteLine("Punkt gotowy.");
}
}
KLASA "PROGRAM"
class Program
{
static void Main(string[] args)
{
Point point = new Point();
}
}
Już! Gwarantuję, że teraz jak uruchomicie program po wklejeniu sobie powyższych kodów do dwóch osobnych plików źródłowych, Waszym oczom ujrzy się podany tekst na strumieniu wyjściowym :). Notabene, że mimo tego faktu nie nałożyłem żadnego wywołania metody, wewnątrz funkcji "Main". Zatem, jedyne wyjaśnienie jest takie, że program wywołał metodę znajdującą się w konstruktorze klasy, czyli musiał go aktywować! Nie ma innej opcji :D.
KONSTRUKTOR KLASY W JĘZYKU C# I SŁOWO KLUCZOWE "THIS"
Najistotniejsze informacje nie kończą się na samym "how-to" w stosunku do tworzenia i wykorzystywania. Jest okazja użycia słówka "this" wewnątrz konstruktora oraz każdej innej metody należącej do tej samej klasy. To jest referencja do samego siebie, czyli do klasy, w której się korzysta ze słowa "this". Bardzo się przydaje w takiej sytuacji jak ta:
private int x, y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
kiedy nazwy parametrów formalnych pokrywają się z etykietami danych składowych. I choć budzący wątpliwości zapis nie będzie sprawiał kłopotu kompilatorowi:
private int x, y;
public Point(int x, int y)
{
x = x;
y = y;
}
to jednak my będziemy potrzebowali jakiegoś odróżnienia i tu nam może pomóc "this". Ten sam klucz przydaje się także do przeciążania konstruktora, czyli zdefiniowania metody o tej samej nazwie, ale z inną listą parametrów. Trzymając się tego samego przykładu z punktem 2D, tak mogłaby wyglądać korzystna technika przeciążania:
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
public Point():this(0, 0)
{
}
Wtedy możemy utworzyć obiekt na dwa sposoby: albo korzystając z wersji dwuargumentowej, albo z wersji bezargumentowej i wtedy zostaną przypisane wartości podane po słowie kluczowym "this":
Point pointA = new Point(8, 3);
Point pointB = new Point();
ALE JA NIE DEFINIOWAŁEM(-AM) ŻADNEGO KONSTRUKTORA!
Nie szkodzi. Kompilator wtedy dodaje od siebie konstruktor domyślny (bezargumentowy), który najprawdopodobniej przyjmuje taką postać:
public [nazwa klasy]() {}
Kiedy dodamy już własny konstruktor klasy w języku C#, wtedy powyższy znika bo już nie jest potrzebny! Wstawiłem ten akapit na wszelki wypadek, żeby nikt nie zaczął wierzyć w "czary mary" :D.
Konstruktor klasy w języku C# to także jest metoda, która wywołuje się JEDEN raz w chwili tworzenia zmiennej instancyjnej.
Nie wydaje się to trudne do opanowania, prawda? Gdybyście się mnie spytali co może być w tym najtrudniejsze, to odpowiedziałbym że największą trudność może sprawić ten "kruczek" w postaci braku typu zwracanej wartości. Ale reszta to pryszcz :).