Menu

C# podstawy, część 5 klasy

4 maja 2016 - blog, C#, kurs
C# podstawy, część 5 klasy

Tworzenie klas i członków klas

W Visual C#, możesz zdefiniować własny typ przez utworzenie klasy. Klasy jako konstrukcje języków programowania, są centralnymi punktami języków zorientowanych obiektowo (object oriented programming). Pozwala to na enkapsulację (zamykanie) zachowań i charakterystyk każdego logicznego bytu (encji) w możliwy do wielokrotnego wykorzystania i rozszerzalny sposób.

W C#, klasa jest konstrukcją, którą możesz użyć aby zdefiniować własny typ danych. Gdy tworzysz klasę, tak naprawdę tworzysz szkic (rysunek techniczny) typu. Klasa definiuje zachowania i charakterystyki (członkowie klasy), które są dzielone przez wszystkie instancje tej klasy. Te charakterystyki i zachowania reprezentujesz definiując metody, pola (field), właściwości (property) oraz zdarzenia (event).

Załóżmy, że tworzysz klasę o nazwie DrinksMachine.

Używasz słowa kluczowego class aby zdefiniować klasę, tak jak na poniższym przykładzie:

 

//Deklarowanie klasy
public class DrinksMachine
{
    // metody, pola, właściwości i zdarzenia deklarujesz tutaj
}

 Słówko class jest poprzedzone modyfikatorem dostępu np. public

Dodawanie członków do klasy

Uzywamy pól oraz właściwości (fields, properties) by zdefiniować charakterystyki maszyny do napojów (naszej DrinksMachine) takie jak producenta, model, wiek, czas do przeglądu. Stworzysz metody aby zaprezentować to co maszyna może zrobić, na przykład zrobić espresso lub zrobić latte. W końcu zdefiniowałbyś eventy (zdarzenia), aby zareprezentować sytuacje, które mogłyby wymagać twojej uwagi, na przykład gdy skończy się kawa w podajniku.

Wewnątrz klasy, możesz dodać metody, pola, właściwości i eventy, tak jak na poniższym przykładzie:

// definiowanie czlonkow klasy
public class DrinksMachine
{

   // ponizej jest zdefiniowana wlasciwosc (property) z prywatnym polem

   private string _location;

   public string Location
   {
      get
      {
         return _location;
      }
      set
      {
         if (value != null) 
            _location = value;
      }
   }

   // ponizej sa definiowane wlasciwosci (properties)

   public string Make {};
   public string Model {};

   // ponizej zdefiniowene sa metody

   public void MakeCappuccino()
   {
      // logika metody
   }

   public void MakeEspresso()
   {
      // logika metody
   }

   // ponizej zdefiniowano event

   public event OutOfBeansHandler OutOfBeans;

}

 Klasy częściowe (Partial Class)

W C# można również implementować klasy częściowe. Klasy częściowe pozwalają na rozdzielenie definicji klasy na kilka plików źródłowych. Podczas kompilacji, wszystkie części są składane do jednego pliku.

Klasy częściowe są użyteczne gdy:

Podczas pracy nad dużymi projektami, rozdzielenie klasy na kilka plików pozwala wielu programistom pracę nad nią w tym samym czasie.

Podczas pracy z automatycznie generowanym kodem. Visual Studio używa tego podejścia gdy tworzysz aplikację Windows Forms, wrapper Web service itp. Microsoft rekomenduje aby nie modyfikować automatycznie generowanego kodu, ponieważ może on zostać nadpisany gdy aplikacja jest kompilowana lub projekt ulega zmianie. W zamian możesz stworzyć kolejną część klasy jako klasę częściową z tą samą nazwą, i tutaj umieścić swój kod.

Przykładowe użycie klasy częściowej

public partial class DrinksMachine
{

   public void MakeCappuccino()
   {
      // logika metody
   }

}

public partial class DrinksMachine
{

   public void MakeEspresso()
   {
      // logika metody
   }

}

 Uwaga: możesz również jako częściowe stworzyć struktury oraz interfejsy

 

Instancjalizowanie klasy

Klasa jest tylko szkicem dla typu. Aby użyć charakterystyki i zachowania, które zdefiniowałeś wewnątrz klasy, musisz stworzyć instancję tej klasy. Instancja klasy nazywana jest obiektem.

Aby stworzyć nową instancję klasy musisz użyć słówka new, jak na poniższym przykładzie:

// Instancjalizacja klasy
DrinksMachine dm = new DrinksMachine();

 Tworząc instancję w ten sposób, właściwie dwie rzeczy się dzieją:

  1. 1. Tworzysz nowy obiekt w pamięci bazujący na typie DrinksMachine
  2. 2. Tworzysz referencję o nazwie dm, która wskazuje na nowy obiekt DrinksMachine

Po zainicjalizowaniu obiektu, możesz użyć dowolnego jej członka - metody, pola, właściwości, eventu, które zdefiniowałeś, używając kropki aby się do nich dostać, tak jak ponizej:

// uzycie członków obiektu
var dm = new DrinksMachine();

dm.Make = "Fourth Coffee";
dm.Model = "Beancrusher 3000";
dm.Age = 2;
dm.MakeEspresso();

 To podejście nazywa się notacją z kropką (dot notation). VisualStudio będzie podpowiadać elementy dostępne wewnątrz twojego obiektu gdy wpiszesz kropkę.

 

Enkapsulacja

Enkapsulacja w  C#

Często uważana za pierwszy filar programowania obiektowego, enkapsulacja może być użyta aby opisać dostępność członków klasy lub struktury. C# daje nam modyfikatory dostępu oraz właściwości (properties) aby ułatwić enkapsulację twojej klasy.

Private vs Public vs Protected vs Internal

Poniższa tabela opisuje modyfikatory dostępu, które mogą być zastosowane do członków klasy aby kontrolować w jaki sposób mogą być dostępne dla innych części twojego programu.

Modyfikator dostępu

Opis

public

Typ dostępny jest dla kodu w każdym assembly, które ma referencję do assembly, w którym jest twoja klasa.

internal

Typ dostępny dla kodu w tym samym assembly, ale nie jest dostępny dla innych assembly

private

Typy dostępne tylko wewnątrz twojej klasy. To jest domyślny modyfikator gdy jego nie określisz.

protected

Typy dostępne tylko wewnątrz twojej klasy oraz dostępny dla klas dziedziczących

Regułą jest: tworzenie prywatnych pól aby zapobiec bezpośredniej manipulacji danymi, i udostępnianie ich przez publiczne właściwości, w których możesz kontrolować cały proces dostępu do danych. Właściwości nazywane są również akcesorami lub getterami i setterami.

 

Properties (właściwości)

Jako część enkapsulacji, powinieneś rozważyć używanie właściwości. Właściwości pozwalają tobie kontrolować użytkownika twojej klasy w momencie zapisywania i odczytywania danych z pól prywatnych. Na przykład możesz kontrolować czy użytkownik podał datę urodzin we właściwym formacie, lub data jest w odpowiednim zakresie.

Poniższy kod prezentuje właściwości

public class DrinksMachine
{
    // prywatne pola
    private int age;
    private string make; 
 
    // publiczne właściwości
    public int Age
    {
        get
        {
            return age;
        }
        set
        {
            age = value;
        }
    }

    public string Make
    {
        get
        {
            return make;
        }
        set
        {
            make = value;
        }
    }
 
    // auto-implementowana właściwość
    public string Model { get; set; }
 
    // Konstruktory
    public DrinksMachine(int age)
    {
        this.Age = age;
    }

    public DrinksMachine(string make, string model)
    {
        this.Make = make;
        this.Model = model;
    }

    public DrinksMachine(int age, string make, string model)
    {
        this.Age = age;
        this.Make = make;
        this.Model = model;
    }
}

 Właściwościami są Age, Make, oraz Model.  Są one wsparte przez prywatne pola nazwane age, make, and model.

Typy właściwości

Możesz stworzyć dwa podstawowe typy właściwości w klasie C#.  Read only (tylko do odczytu) oraz  read-write (do zapisu i odczytu):

Akcesor  get używany jest aby zwrócić wartość właściwości

Akcesor  set używany jest aby przypisać nową wartość. Pominięcie tego spowoduje, że property będzie tylko do odczytu.

Słowo kluczowe value użyte jest aby określić "wartość" przypisywaną przez akcesor set.

Właściwości, które nie implementują akcesora set są tylko do odczytu.

Dla prostych właściwości, które nie wymagają własnego kodu akcesorów, warto używać auto-właściwości (auto-properties).

Gdy deklarujesz auto-properties, kompilator automatcznie stworzy prywatne, anonimowe pola w tle, które będą dostępne tylko przez gettery i settery.

Poniżej są przykłady auto-właściwości

// Auto-implementowane właściwości
public double TotalPurchases { get; set; }
public string Name { get; set; }
public int CustomerID { get; set; }

 

 

Używanie konstruktorów

 

Czytając artykuł powyżej, w sekcji instancjalizacja klas zauważysz taką linijkę kodu:

DrinksMachine dm = new DrinksMachine();

 Zauważ, że składnie jest podobna do wywoływania metody. Tak jest, ponieważ gdy powołujesz instancję klasy, tak włąściwie wywołujesz specjalną metodą zwaną konstruktorem. Konstruktor jest metodą w klasie o tej samej nazwie co klasa. Konstruktory nie zwracają żadnej wartości, co więcej nie można w ich deklaracji użyć słówka void. Konstruktory, są zazwyczaj używane do dostarczenia początkowych wartości dla członków klasy (pól i właściwości).

// tworzenie konstruktora
public class DrinksMachine
{

    public int Age { get; set; }

    public DrinksMachine()
    {
        Age = 0;
    }

}

 Konstruktor, który nie przyjmuje żadnych parametrów jest konstruktorem domyślnym. Jeśli w swojej klasie nie umieścisz żadnego konstruktora, to kompilator C# automatycznie stworzy konstruktor domyślny w skompilowanym pliku.

W wielu przyadkach, przydatne jest dla uzytkownikó twojej klasy aby móc określić wartości początkowe dla członków twojej klasy w momencie, gdy tworzony jest obiekt. Na przykłąd, gdy ktoś tworzy nową instancję klasy DrinksMachine, będzie przydatne gdyby mogli określić producenta oraz model w tym samym czasie. Twoja klasa może zawierać wiele konstruktorów, przyjmujących różne parametry, które pozwolą użytkownikom kodu na inicjalizowanie obiektów z różnymi wartościami. Przypomnij sobie metody przeciążone.
Poniższy przykład pokazuje dodanie kilku konstruktorów do klasy

// dodanie wielu konstruktorów
public class DrinksMachine
{

    public int Age { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }

    public DrinksMachine(int age)
    {
        this.Age = age;
    }

    public DrinksMachine(string make, string model)
    {
        this.Make = make;
        this.Model = model;
    }

    public DrinksMachine(int age, string make, string model)
    {
        this.Age = age;
        this.Make = make;
        this.Model = model;
    }

}

 Konsumenci twojej klasy mogą użyć dowolny z konstruktorów aby stworzyć instancję twojej klasy, w zależności od informacji, którą maja w danym czasie. Na przykład:

// wywołanie konstruktorów
var dm1 = new DrinksMachine(2);
var dm2 = new DrinksMachine("Fourth Coffee", "BeanCrusher 3000");
var dm3 = new DrinksMachine(3, "Fourth Coffee", "BeanToaster Turbo");