Blog Dla Młodszych Programistów C#/.NET

26 maja 2020
Nadszedł czas na kolejny, tym razem 4 filar programowania obiektowego. W poprzednich artykułach na temat podstaw programowania obiektowego dowiedziałeś się, czym jest dziedziczenie, polimorfizm, a także abstrakcja. Dzisiaj postaram Ci się pokazać, na czym polega hermetyzacja, na przykładzie w C#. Jeżeli chcesz zostać młodszym programistą .NET, koniecznie musisz zrozumieć te 4 pojęcia.

Co To Jest Hermetyzacja w Programowaniu Obiektowym?


Czym jest hermetyzacja?


Hermetyzacja, inaczej również enkapsulacją, polega na ukrywaniu pewnych danych. Często jest tak, że tworząc jakąś klasę, nie chcemy, żeby poszczególne jej składowe, mogły zostać zmieniane z zewnątrz, ponieważ takie sytuacje mogą doprowadzić do nieprawidłowego działania naszych aplikacji. To znaczy, im więcej udostępniamy na zewnątrz, tym bardziej może to być niebezpieczne. Wyobraź sobie, że piszesz jakąś aplikację bankową i masz klasę dla konta bankowego. A w niej, pole stan konta, jest to pole dość wrażliwe i nie chcesz go udostępniać na zewnątrz, nie chce, żeby na przykład ktoś z zewnątrz zmienił wartość tego pola. Dlatego taki element powinien zostać ukryty wewnątrz klasy, bez możliwości zmieniana go z zewnątrz.


Hermetyzacja w C#


Nasze dane powinny być jak najbardziej ukrywane wewnątrz klasy. Na zewnątrz powinno być ujawniane jak najmniej. W C# istnieje kilka sposobów hermetyzacji danych. Są to między innymi:
  • modyfikatory dostępu,
  • właściwości,
  • stałe (const),
  • zmienne tylko do odczytu (readonly).
Zauważyłeś na pewno, że zazwyczaj deklaracja pola, metody czy klasy, jest poprzedzona jakimś słowem kluczowym, może to być:
  • private,
  • public,
  • protected,
  • internal,
  • protected internal.
To są właśnie podstawowe modyfikatory dostępu, które opisuje poziom dostępu - hermetyzacji. Jeżeli brakuje jawnie podanego modyfikatora dostępu, to domyślnie dla składowych klasy (pól, metod, właściwości) jest to private, a dla klas internal.


Modyfikator public


Element oznaczony tym atrybutem jest dostępny wszędzie, z każdego miejsca wewnątrz i z zewnątrz klasy.

public class Person
{
    public string FirstName;        
}

public class Program
{
    static void Main(string[] args)
    {
        var person = new Person();
        person.FirstName = "Kazimierz";
    }
}

Możemy stworzyć nowy obiekt klasy Person, a następnie zawsze i z każdego miejsca możemy zmodyfikować pole FirstName.


Modyfikator private


Element oznaczony tym modyfikatorem jest dostępny tylko w tej samej klasie, w której został stworzony.

public class Person
{
    private string _pesel;
}

public class Program
{
    static void Main(string[] args)
    {
        var person = new Person();
        person._pesel = "88888888888";//Error!!!
    }
}

W powyższym przykładzie, z zewnątrz klasy Person nie mamy możliwości odwołać się pola _pesel. Zazwyczaj modyfikatorem private są oznaczone jakieś szczegóły implementacji, istotne dane, które nie powinny być widoczne, zmieniane z zewnątrz.


Modyfikator protected


Element oznaczony poprzez protected jest dostępny tylko w klasie, w której został utworzony, a także w klasach pochodnych. To znaczy klas, które dziedziczą po klasie, w której został zadeklarowany ten element.

public class Person
{
    protected string LastName;
}

public class Employee : Person
{
    public Employee()
    {
        LastName = "Szpin";
    }
}
public class Program
{
    static void Main(string[] args)
    {
        var person = new Person();
        person.LastName = "Szpin";//Error!!!
    }
}

Podobnie jak w przypadku modyfikatora private, pole LastName nie jest widoczne na zewnętrz klasy. Może być tylko widoczne w klasach pochodnych, w powyższym przykładzie w klasie Employee. Czasem ten modyfikator może być niebezpieczny, ponieważ udostępniamy jakieś szczegóły wszystkim klasom dziedziczącym.


Modyfikator internal


Dostępność dla danego elementu tylko w tym samym module.

internal class Person
{
}

public class Program
{
    static void Main(string[] args)
    {
        var person = new Person();
    }
}

To znaczy, jeżeli klasy Program i Person, będą w tym samym module, to wtedy powyższy kod będzie się kompilował, nie będzie zgłoszonego błędu. Jednak jeżeli te 2 klasy będą w osobnych modułach, to nie będzie można użyć klasy Person w klasie Program, zostanie wtedy zgłoszony błąd kompilacji.


Modyfikator protected internal


Oznacza dostępność dla wszystkich w danym module oraz dla każdej klasy pochodnej. Czyli jest tak jakby sumą dostępów protected i internal.

public class Person
{
    protected internal int Age;
}

public class Program
{
    static void Main(string[] args)
    {
        var person = new Person();
        person.Age = 30;
    }
}

Najrzadziej używany modyfikator, jeszcze chyba nie zdarzyło mi się, żebym potrzebował go użyć w swoich aplikacjach, ale warto, żebyś wiedział, że taki istnieje.


Właściwości


Zazwyczaj nie tworzymy publicznych pól, zamiast tego zazwyczaj lepiej utworzyć właściwość, która może oprócz przypisania danych zawierać w sobie dodatkowe informacje, na przykład dodatkową walidację wprowadzanych danych.

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; private set; }

}

public class Program
{
    static void Main(string[] args)
    {
        var person = new Person();
        person.FirstName = "Jan";
        person.LastName = "Kowalski";//Error!!!
    }
}

We właściwościach możesz również nadać modyfikatory dostępów. W powyższym przykładzie właściwość LastName ma prywatny setter, co oznacza, że może ona być zmieniona tylko wewnątrz klasy.


Modyfikator const


Wartość pola oznaczona tym modyfikatorem, nie może zostać zmieniona w trakcie działania programu. Jest to stała, której wartość zostaje określona w czasie kompilacji. Stosuje się do wartości, które nigdy się nie zmieniają. Na przykład wartość liczby PI. Pole oznaczone modyfikatorem const jest traktowane jako pole statyczne.

public class Math
{
    public const double PI = 3.14159;
}

public class Program
{

    static void Main(string[] args)
    {
        Console.WriteLine(Math.PI);
    }
}


Modyfikator readonly


Wartość pola oznaczona tym modyfikatorem może zostać przypisana zarówno w czasie kompilacji, jak i w trakcie działania programu, ale tylko przy inicjalizacji i w konstruktorze. Również, w przeciwieństwie do const, może być wartością instancyjną, nie tylko statyczną.

public class Person
{
    private readonly string _name;

    public Person(string name)
    {
        _name = name;
    }
}


PODSUMOWANIE:


W dzisiejszym artykule starałem się Ci przekazać najważniejsze informacje o hermetyzacji (enkapsulacji) danych w C#. Dzięki hermetyzacji możesz ukryć różne wrażliwe dane lub szczegóły implementacji wewnątrz swojej klasy. Pomaga Ci się zabezpieczyć przez niepożądanym zachowaniem. Pamiętaj, żeby na zewnątrz udostępniać jak najmniej danych. Tylko to, co jest koniecznie. Zapamiętaj najważniejsze modyfikatory dostępów. Przede wszystkim zapamiętaj, jak działa modyfikator public, private, protected i internal, bo to one są najczęściej używane, często na rozmowach kwalifikacyjnych na stanowisko młodszego programisty C#, możesz zostać o nie zapytany (więcej). To tyle na dziś, powoli kończymy cykl artykułów o programowaniu obiektowym w C#, kolejny artykuł w następny wtorek. Jeżeli jeszcze masz jakieś pytania co do tego artykułu lub chciałbyś poczytać o jakimś konkretnym materiale, to napisz do mnie maila, lub zostaw komentarz.

Poprzedni artykuł - Co To Jest Abstrakcja w Programowaniu Obiektowym?.
Następny artykuł - 7 Najlepszych Blogów o Programowaniu w 2020.
Autor artykułu:
Kazimierz Szpin
Kazimierz Szpin
Programista C#/.NET. Głównie pisze aplikacje w ASP.NET MVC, WPF oraz Windows Forms. Specjalizuje się w testach jednostkowych.
Autor bloga ModestProgrammer.pl
Dodaj komentarz
© Copyright 2020 modestprogrammer.pl. Wszelkie prawa zastrzeżone. Polityka prywatności. Design by Kazimierz Szpin