KlasaCzęść NR.8

Klasa jest to szablon używany do tworzenia obiektów. Klasy składają się głównie z dwóch członów: pól i metod. (C# ma tego więcej)

Pola są zmiennymi, które trzymają stan obiektu. Metody definiują, co obiekt potrafi.

Poniżej znajduje się klasa opisująca kwadrat. Ma ona dwa pola x i y oraz metodę GetArea().

class MyRectangle
{
    int x, y;
    int GetArea() { return x * y; }
}

Tworzenie obiektu

Aby uzyskać dostęp do pól i metod poza definicją klasy trzeba najpierw utworzyć obiekt.

Utworzenie obiektu polega na użyciu słowa kluczowego “new”. Tak w pamięci powstanie nowy obiekt.

public class MyApp
{
    public static void main(String[] args)
    {
        // Create an object of MyRectangle
        MyRectangle r = new MyRectangle();
    }
}
class Program
{
    static void Main(string[] args)
    {
        MyRectangle r = new MyRectangle();
    }
}

Obiekt jest również nazywany instancją klasy. Obiekt będzie zawierał swój własny zbiór pól, które będą przetrzymywać wartości . Będą one inne i nie będą one powiązane z innymi polami wewnątrz innych instancji tej klasy.

Dostęp do elementów wewnątrz klasy

Aby elementy wewnątrz instancji klasy były dostępne poza jej paczką w Javie, muszą być one zadeklarowane słowem kluczowym “public”.

Dostęp do elementów wewnątrz klasy

W C# pola domyślne są prywatne, więc bez słowa public nie można uzyskać do nich dostępu, jeśli jesteś poza definicją tej klasy.

Metody obiektu

Po użyciu słowa public można odwołać się do pól.

class MyRectangle
{
    public int x, y;
    int GetArea() { return x * y; }
}

public

Konstruktor

Klasa może mieć konstruktor. Konstruktor jest to specjalny rodzaj metody, która się wywołuje w trakcie tworzenia obiektu.

Nazywa się ona tak samo jak klasa i nie zwraca żadnej wartości. Chociaż oczywiście konstruktor zwraca instancje klasy, tylko robi to niejawnie.

Konstruktor, aby mógł być wywoływany przez inne paczki w Javie, musi mieć poziom dostępu public.

public class MyRectangle
{
    int x, y;
    int GetArea() { return x * y; }
    
    public MyRectangle() {
        x = 10;
        y = 10;
    }
}

Ten konstruktor może przyjmować parametry jak metoda . Oto przykład:

class MyRectangle
{
    public int x, y;
    int GetArea() { return x * y; }

    public MyRectangle(int _x,int _y)
    {
        x = _x;
        y = _y;
    }
}

Słowo kluczowe this

Wewnątrz konstruktora jak w innych metodach należących do obiektu specjalne słowo kluczowe “this” może zostać użyte. Słowo kluczowe “this” jest referencją do obecnej instancji obiektu.

Przykładowo jeśli parametry konstruktora mają taka samą nazwę jak pola klasy wtedy użycie słowa kluczowego “this” rozwiąże problem przykrywania/cieniowania zmiennych.

public class MyRectangle
{
    int x, y;
    int GetArea() { return x * y; }
    
    public MyRectangle(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

Przeciążanie konstruktorów

Aby wspierać różne listy parametrów w konstruktorze istnieje możliwość ich przeciążania. W przykładzie poniżej znajdują się 3 konstruktory.

Pierwszy konstruktor nie przyjmuje parametrów. Drugi przyjmuje tylko jeden parametr. A ostatni dwa.

Próba użycia konstruktora, którego nie ma, czyli jeśli podamy inne typy parametrów lub podamy ich za dużo, czy za mało - to skutkuje błędem kompilacji.

public class MyRectangle
{
    int x, y;
    public MyRectangle() { x = 10; y = 20; }
    public MyRectangle(int a) { x = a; y = a; }
    public MyRectangle(int a, int b) { x = a; y = b; }
}

Łańcuchy wywołań konstruktorów

Użycie słowa kluczowego this umożliwia wywołanie jednego konstruktora wewnątrz innego.

Pozwala to na ponowne użycie kodu.

public class MyRectangle
{
    int x, y;
    public MyRectangle() { this(10,20); }
    public MyRectangle(int a) { this(a,a); }
    public MyRectangle(int a, int b) { x = a; y = b; }
}

Warto zaznaczyć, że wywołanie konstruktora wewnątrz konstruktora wygląda jak wywołanie metody. Inna sprawa, wywołanie musi być w pierwszej linijce konstruktora głównego.

Inicjalizowanie wartości pól

istnieje możliwość nadania domyślnych wartości pól zanim konstruktor zostanie wywołany.

Pola będą miały te wartości w trakcie ich deklaracji.

public int x = 10;
public int y = 10;

Pola, które nie są uzupełnione zostaną wypełnione domyślnymi wartościami dla swojego typu.

Domyślny konstruktor

Istnieje możliwość stworzenia klasy bez konstruktora. Jak to możliwe?

Kompilator tworzy bezparametrowy konstruktor automatycznie.

Jeśli jednak utworzyliśmy nawet jeden konstruktor parametrowy kompilator nie stworzy domyślnego konstruktora. Zakłada on, że jest to zachowanie, które chcemy mieć.

brak domyślnego konstruktora

NULL

Wbudowana stała NULL reprezentuje nieutworzony obiekt. Może ona zostać przypisana do zmiennych, które nie są typami wartościowymi/prostymi.

MyRectangle s = null;
if (s == null) s = new MyRectangle(1,2);

Domyślne wartości

Domyślne wartości obiektów typów referencyjnych są reprezentowane przez NULL.

Dla typów liczbowych jest to zero.

Dla char czyli znaku jest to wartość \0000 reprezentująca zero.

Dla zmiennej logicznej jest to wartość false.

Mimo, iż istnieje taki mechanizm warto definiować domyślne wartości swoich zmiennych tak, by działanie programu było bardziej oczywiste.

class Johny
{
    int numberOfNoses; // pole domyślnie ma przypisaną wartość 0
    int Metoda()
    {
        int numberOfNoses; // lokalna zmienna musi mieć przypisaną wartość
        
    }
}

Dla lokalnych zmiennych kompilator nie ustawia domyślnych wartości. Kompilator w formie błędu kompilacji wymusi na programiście uzupełnienie lokalnej zmiennej.

Kompilator w ten sposób chce uniknąć użycia nieprzypisanych zmiennych.

Garbage Collector

Środowisko Javy i .NET mają swoje Garbage Collector-y. Zajmują się one czyszczeniem pamięci z obiektów, które nie są już używane przez program.

Co to oznacza? Oznacz to, że w C# i Javie nie musimy zarządzać destrukcjami (zwalnianiem pamięci) obiektów jak np. w języku C++.