Programowanie w języku C#

Pola

  • 2012-03-09 06:58
  • 0 komentarzy
  • 6234 odsłony
  • Oceń ten tekst jako pierwszy

Czym są pola


Polem nazywana jest zmienna zadeklarowana w klasie, przechowująca jakąś wartość. Wartość ta może być typu prostego lub referencyjnego. Ogólnie rzecz ujmując pola służą do przechowywania danych wewnątrz klasy.
Jak podaje literatura - pola wraz z właściwościami oraz stałymi, obrazują faktyczną zawartość klasy lub stan obiektu utworzonego na podstawie tej klasy.

Można by się pokusić o stwierdzenie, że to normalna zmienna, a całe to nazewnictwo to „chłyt matetingody” twórców języka, jednak w przeciwieństwie do zmiennych pole, jeżeli nie zostanie zainicjowane - nie ważne czy w miejscu zadeklarowania czy w konstruktorze klasy -po utworzeniu obiektu danej klasy automatycznie przyjmie swoją wartość domyślną, odpowiednio:
•        dla typów liczbowych będzie to 0,
•        dla łańcucha pusty ciąg oznaczany jako ""
•        dla typu boolean wartość false;
•        a dla typów referencyjnych null.
(Co będzie wartością domyślną dla pól typu enum lub struktur, moża sprawdzić samemu np. definiując jedno pole typu wyliczeniowego płeć, oraz date urodzenia jako strukture DateTime, szybko można się zorientować co będzie wartością domyślną dla każdegoz tych typów)

Przykład 1:
        class Czlowiek
        {
            public string imie;                    //3 pola typu prostego, klasy Czlowiek
            public string nazwisko;                //
            public int wiekWLatach;                //
            public Charakter tupet;                //1 pole typu referencyjnego
 
            public Czlowiek(string nazwiskoRodzicow)
            {
                nazwisko = nazwiskoRodzicow;        //tylko jedno pole zostaje zainicjowane w momencie tworzenia nowego obiektu klasy Czlowiek
            }
 
            public void JakasMetodaJednaZWieluTejKlasy()
            {
                //jakis kod metody
            }
        }
 
        class Charakter
        {
            //jakies skladowe klasy Charakter
        }


Jak widać na przykładzie powyżej, żadne pole w momencie deklaracji nie zostało zainicjowane wartością, natomiast w konstruktorze klasy, tylko pole nazwisko, zostało zainicjowane wartością przekazaną w parametrze konstruktora. Pomimo to, w nowo utworzonym obiekcie klasy człowiek, pola przyjęły odpowiednio wartości:
 
        imie = "";
        nazwisko = "Nowak";  //Nowak – pod warunkiem ze z takim parametrem utworzymy nowy obiekt
        wiekWLatach = 0;
        tupet = null;

Powyższy przykład można odnieść do świata rzeczywistego.
Człowiek w chwili narodzin przyjmuje nazwisko rodziców, dlatego w konstruktorze klasy Człowiek dla pola nazwisko, przypisywane jest nazwisko rodziców.
Pole imie - nowy obiekt (dziecko) będzie miało, ale dopiero za jakiś czas jak się rodzice zdecydują, także to pole będzie ustawione/zainicjowane dopiero po jakimś czasie od utworzenia obiektu człowiek. Skoro nie ma przypisania wartości do tego pola ani w klasie ani w konstruktorze tej klasy, pole to zaraz po utworzeniu obiektu będzie przechowywało wartość „”. Czyli nasz kod w tym przypadku również odzwierciedla rzeczywistość.
Pole wiekWLatach - w chwili utworzenia nowego obiektu klasy Człowiek, pole to  ma przypisaną wartość domyślną, dla typu int będzie to 0. Po urodzeniu człowiek ma pare sekund życia, do pierwszego roczku troche brakuje, odnosząc to do świata rzeczywistego również znajdujemy tu pewne podobieństwo.
Pole tupet typu Charakter – to pole nie zostało zainicjowane ani w klasie ani w konstruktorze, zatem w momencie utworzenia nowego obiektu przyjmie jako swoją wartość domyślną null. Może to niezbyt trafione zestawienie ale wydaje mi się dobrze ilustruje, że w przypadku niektórych pól należałoby się zastanowić czy i jak je inicjować w momencie tworzenia obiektów. Człowiek po urodzeniu i odcięciu pępowiny zaczyna płakać (odrobinę naciągając możemy uznać płacz jako wyrażenie rodzaju charakteru). Może wrzeszczeć, kwilić, łkać lub inteligentnie popłakiwać ale jakoś płakać musi.

To, czy faktycznie takie będą wartości naszych pól, możemy w bardzo łatwy sposób sprawdzić za pomocą poniższego kodu:

Przykład 2:
 
            Czlowiek ludzik = new Czlowiek("Nowak");
 
            Console.WriteLine("Nazwisko nowego ludzika: {0}", ludzik.nazwisko);
            Console.WriteLine("Imie nowego ludzika: {0}", ludzik.imie);
            Console.WriteLine("Ilość przeżytych pełnych lat nowego ludzika: {0}", ludzik.wiekWLatach);
            Console.ReadLine();


Modyfikatory  pól


Oczywiście ten kod nie zostanie skompilowany dla klasy z początku artykułu i bardzo słusznie. Chodzi o modyfikatory dostępu. W kodzie klasy nie opisaliśmy żadnego pola modyfikatorem dostępu a w takich przypadkach kompilator zakłada modyfikator domyślny czyli private. Ogólnie pola mogą być definiowane z następującymi atrybutami:
 
            private
            public
            internal
            protected

Aby kod z przykładu 2 zadziałał, należałoby w przykładzie 1 wszystkie pola klasy Człowiek zdefiniować jawnie jako public.
Wtedy owszem kod z przykładu 2 zadziała ale to nie będzie kod którym będzie się można pochwalić. Zgodnie ze wszelkimi źródłami z literatury i dobrymi zasadami programowania obiektowego pola powinny być definiowane z atrybutem private, ponieważ tylko wtedy zabezpieczamy je przed niepożądaną modyfikacją z zewnątrz. Jeżeli bardzo musimy, możemy udostępnić wartości pól na zewnątrz klasy, powinniśmy w takim wypadku zawsze korzystać z właściwości.

Poza wymienionymi modyfikatorami dostępu, w stosunku do pól stosuje się w niektórych przypadkach dwa dodatkowe modyfikatory:
 
            static
            readonly

W przypadku oznaczenia pola jako readonly oznacza to ze pole jest tylko do odczytu, jest czymś w rodzaju stałej, jednak od stałej różni się tym, że wartość do pola oznaczonego jako readonly możemy przypisać w chwili deklaracji takiego pola lub w konstruktorze klasy.

Jeżeli oznaczymy pole jako static oznacza to, że takie pole jest częścią stanu klasy a nie konkretnego obiektu. Innymi słowy aby odwołać się do takiego pola nie musimy tworzyć obiektu danej klasy jak było to przedstawione w przykładzie 2, a wystarczy to zrobić za pomocą operatora kropki pisanego bezpośrednio po nazwie klasy. Aby to przedstawić na przykładzie dodajmy do klasy Człowiek z przykładu 1, statyczne pole:
            public static string stopienEwolucji = "homo-sapiens";
 

(pole jako public, ale tylko w celu czytelności przykładu)

Możemy odwołać się do takiego pola tylko tak:
 
            Console.WriteLine("Jedyny występujący współcześnie gatunek z rodzaju człowiek (Homo) - {0}", Czlowiek.stopienEwolucji);
            Console.ReadLine();

Próba odwołania się do pola statycznego z poziomu obiektu, jak pokazano poniżej:
 
            Czlowiek ludzik = new Czlowiek("Nowak");
            Console.WriteLine("Jedyny występujący współcześnie gatunek z rodzaju człowiek (Homo) - {0}", ludzik.stopienEwolucji);
            Console.ReadLine();

spotka się z błędem kompilatora.
 
Member 'ConsoleApplication4p_pola.Program.Czlowiek.stopienEwolucji' cannot be accessed with an instance reference; qualify it with a type name instead”


Uwagi


- zgodnie z konwencją nazewniczą, nazwy pól piszemy z małej litery , jeżeli nazwa pola składa się z kilku wyrazów to pierwszy piszemy z małej litery a każdy kolejny z wielkiej.