UWAGA! Promocja dla firm - MICROSOFT OFFICE 365  na 12 miesiecy ZA DARMO! Tylko na CentrumXP.pl!
Wielka promocja Office 365 na CentrumXP.pl!
Do góry Skomentuj

04. Przeciążanie metod i konstruktorów

04. Przeciążanie metod i konstruktorów

Autor: Paweł Kruczkowski Opublikowano: 17 października 2006 Odsłon: 46 315

Na początku wprowadźmy sobie pojęcie sygnatury. Sygnatura jest to nazwa metody oraz lista parametrów, jakie ta metoda przyjmuje. Mówimy więc, że dwie metody mają różne sygnatury, gdy nazywają się inaczej, bądź mają różną listę parametrów (co do liczby lub ich nazwy). Spójrzmy na poniższy fragment kodu:

public int MojaMetoda(int param1);
      public int MojaMetoda(int param1, int param2);
      public int MojaMetoda(int param1, int param2, int param3);
      public int MojaMetoda(int param1, double param2, string param3);

Pierwsze trzy metody mają taka samą nazwę oraz zwracają ten sam typ, ale różnią się ilością parametrów jakie przyjmują. Natomiast trzecia metoda różni się od czwartej typem dwóch parametrów, jakie ta czwarta metoda przyjmuje (double param2, string param3).

A więc przeciążenie metody (ang. Method overloading) – czyli innymi słowy utworzenie nowej wersji metody, polega na zmianie sygnatury tej metody (zmianie nazwy metody lub liczby parametrów jaką ta metoda przyjmuje, lub zmianie typu parametrów metody).

Napiszmy więc pierwszy przykład, który będzie ilustrował przeciążanie metod:

class Przeciazenie
{
     public void MojaMetoda()
     {
         System.Console.WriteLine("Brak parametrów w metodzie.");
     }
     //przeciazenie metody mojaMetoda() - dodanie jednego parametru
     public void MojaMetoda(int param1)
     {
         System.Console.WriteLine("Jeden parametr w metodzie, którego wartość wynosi: {0}", param1 + ".");
     }
     //przeciazenie metody mojaMetoda() - dodanie dwoch parametrow
     public void MojaMetoda(int param1, int param2)
     {
         System.Console.WriteLine("Dwa parametry w metodzie. Parametr pierwszy to: {0}, a parametr drugi to: {1}", param1,param2 + ".");
     }
     //przeciazenie metody mojaMetoda() - parametr typu string
     public string MojaMetoda(string param1)
     {
         return param1;
     }
}
 
class Glowna
{
    static void Main()
    {
        string napis;
        //obiket klasy Program
        Przeciazenie prz = new Przeciazenie();
        //wywolanie przeciazonych metod z klasy Przeciazenie
        prz.MojaMetoda();
        prz.MojaMetoda(8);
        prz.MojaMetoda(8, 23);
        napis = prz.MojaMetoda("CentrumXP.pl");
 
        System.Console.WriteLine("Nasz napis to: {0}", napis + ".");
    }
}

W wyniku uruchomienia powyższego przykładu otrzymamy następujące wyniki:

Jak widać, metoda MojaMetoda() jest przeciążana 4-krotnie. Pierwsza wersja tej metody nie przyjmuje żadnego parametru. Druga wersja przyjmuje jeden parametr (jest to liczba całkowita). Natomiast trzecia wersja metody MojaMetoda() przyjmuje dwa parametry, które również są liczbami całkowitymi.

Wreszcie czwarta wersja przyjmuje jeden parametr, który jest typu string. A więc przeciążenie tutaj polega na zmianie typu parametru tej metody. Ta wersja metody różni się od swoich poprzedniczek również typem jaki zwraca (pierwsze trzy metody MojaMetoda() zwracają typ intiger, natomiast ta - czwarta jest typu string).Wprowadzona przez nas definicja przeciążania mówi o różnicach sygnatur między kolejnymi wersjami metod (wersja czwarta niewątpliwie spełnia ten wymóg), natomiast nic nie mówi o typach zwracanych przez poszczególne metody. Czy zmiana tylko typów zwracanych przez dwie metody przy niezmiennej sygnaturze tych metod sprawi, że obie metody będziemy uważać za przeciążone?

Jak się pewnie domyślamy, zmiana samego typu zwracanego nie tworzy nowej wersji metody, a samo utworzenie dwóch metod o tej samej sygnaturze, ale innym typie zwracanym, spowoduje, że w trakcie kompilacji otrzymamy błąd (można spróbować napisać sobie w ramach pracy domowej przykład takiej sytuacji i upewnić się, że tak naprawdę jest).

W poniższym przykładzie natomiast, przeciążymy dwukrotnie metodę, której druga wersja przyjmie inny typ parametru (nazwy parametrów będą w obu metodach te same) oraz zwróci inny typ niż jej poprzedniczka (pierwsza metoda będzie zwracać intiger, natomiast druga: typ o nazwie long).

Oto przykład:

class Przeciazenie
{
    public int MojaMetoda(int liczba1)
    {
        return 10 + liczba1;
    }
 
    public long MojaMetoda(long liczba1)
    {
        return 20 + liczba1;
    }
}
class Glowna
{
    static void Main()
    {
        int a;
        int b;
        Przeciazenie prz = new Przeciazenie();
        a = prz.MojaMetoda(10);
        b = prz.MojaMetoda(30);
        System.Console.WriteLine("Wynik po wywołaniu pierwszej metody wynosi: {0}", a);
        System.Console.WriteLine("Wynik po wywołaniu drugiej metody wynosi: {0}", b);
    }
}

Po uruchomieniu będziemy mieli następujące wyniki:

A więc jak widzimy, taki sposób przeciążania metody jest jak najbardziej prawidłowy i dozwolony. Pomimo faktu, że sposób ten nie jest najczęściej wykorzystywany przez programistów to pamiętajmy, że można i tak przeciążać metody.

Podsumowując przeciążanie metod w języku C#, powiemy, że polega ono po prostu na tworzeniu nowych wersji tych metod poprzez zmianę ich sygnatur (czyli nazwy i listy parametrów metody przeciążanej). Klasa może zawierać dowolną liczbę metod, o ile każda metoda ma inną, unikalną sygnaturę. Każda inna sytuacja spowoduje, że podczas przeciążania metod, nasz kompilator wyświetli komunikat o błędzie.

Na koniec przejdźmy do przeciążanie konstruktorów.Podobnie jak w metodach, tak i w konstruktorach możemy używać mechanizmu przeciążania. Mechanizm ten nie będzie różnił się niczym szczególnym w stosunku do zwykłego przeciążania metod.

Napiszmy program, który będzie w zupełności przedstawiał mechanizm przeciążania konstruktorów. Program ten będzie obliczał pole kwadratu (gdy podamy jeden wymiar), pole prostokąta (gdy podamy 2 wymiary). Oto przykładowy program:

public class Figura
{
    int a;
    int b;
 
    //pierwszy konstruktor, ktory używany jest, gdy nie podamy żadnego wymiaru
    public Figura()
    {
        a = 0;
        b = 0;
    }
    //drugi konstruktor, który używany jest, gdy tworzony jest kwadrat
    public Figura(int bok)
    {
        a = b = bok;
    }
    //trzeci konstruktor, ktory uzywany jest, gdy tworzony jest prostokat
    public Figura(int bok1, int bok2)
    {
        a = bok1;
        b = bok2;
    }
    //metoda, ktora oblicza pole odpowiedniej figury
    public int Oblicz()
    {
         return a * b;
    }
}
 
class Glowna
{
    public static void Main(string[] args)
    {
        int wynik;
        //tworzymy figury, uzywajac roznych konstruktorow
        Figura figura1 = new Figura();
        Figura figura2 = new Figura(5);
        Figura figura3 = new Figura(6);
 
        //podaje pole pierwszej figury
        wynik = figura1.Oblicz();
        System.Console.WriteLine("Pole pierwszej figury wynosi: {0}", wynik);
 
        //podaje pole drugiej figury
        wynik = figura2.Oblicz();
        System.Console.WriteLine("Pole drugiej figury wynosi: {0}", wynik);
 
        //podaje pole trzeciej figury
        wynik = figura3.Oblicz();
        System.Console.WriteLine("Pole trzeciej figury wynosi: {0}", wynik);
    }
}

Po skompilowaniu, otrzymujemy następujące wyniki:

W powyższym przykładzie klasa Figura posiada 3 konstruktory: pierwszy używany jest w programie przy inicjalizacji obiektu: figura1, gdy nie podamy żadnego wymiaru boku. W ten sposób w konstruktorze tym, odpowiednim zmiennym przypisywana jest wartość 0, stąd metoda Oblicz() (metoda ta oblicza pole na podstawie podanych wymiarów) zwraca dla tego przypadku pole równe 0.

Drugi konstruktor używany jest przy inicjalizacji obiektu: figura2, gdy podamy jeden wymiar boku. W ten sposób metoda Oblicz() zwróci pole równe 25 (podaliśmy jeden wymiar, więc zbudowaliśmy kwadrat). Natomiast trzeci konstruktor używany jest przy tworzeniu obiektu: figura3. Jest to przypadek, gdy w konstruktorze podaliśmy 2 wymiary i metoda Oblicz() zwróci nam pole dla prostokąta (pole w naszym programie wynosi: 36).

Dzisiaj opowiedzieliśmy sobie o przeciążaniu metod oraz konstruktorów. Są to mechanizmy bardzo często wykorzystywane przez programistów i na pewno stanowią regułę, a nie wyjątek.

Za tydzień opowiemy sobie o hermetyzacji danych w języku C# 2.0.

Zobacz również

Komentarze

w tym przykladzie dwa razy wywolana zostala pierwsza metoda ... kompilator przyjmuje ze 10 i 30 to integery (najzupelniej poprawnie), wiec nie widze za bardzo mozliwosci takiego przeciazenia. PS. kurs super :)
Parn, 20 maja 2007, 16:19
w przykładzie o przeciążeniu konstruktora, str3, moim zdaniem konstruktor: public Figura(int bok1, int bok2); jest niewykorzystany, Ponieważ przyjmuje 2 parametry, a odpowiedni wywołanie do niego jest: Figura figura3 = new Figura(6); tak wiec 2 razy wywołany jest konstruktor: public Figura(int bok).
rakuzan, 2 lipca 2007, 15:04
Podpisuje sie pod obydwoma poprzednimi postami. Drobne niedociagniecia, ale zawsze. Mam natomiast pytanie na ktore nie znalazlem odpowiedzi w tym artykule. Po co przeciazac metody i narazac sie na pogubienie w nich? nie latwiej i bezpieczniej tworzyc nowe metody?
Michal, 7 lipca 2007, 01:02
Jeżeli metoda ma robić z grubsza to samo lecz na różnych typach danych wtedy zwykle używamy przeciążania.
tinamou, 28 sierpnia 2007, 18:08
Prozaiczny przykład: robisz funkcję dodaj(int a, int b) { return a + b; } Po roku okazuje się, że potrzebna jest taka sama tylko z double. Odszukujesz poprzednią metodę (wśród mnóstwa innych) i zmieniasz jej nazwę dodaj_int(int a, int b) { return a + b; } dodaj_double(double a, double b) { return a + b; } Później musisz dodać kolejną. dodaj_klasa(klasa a, klasa b) { return a + b; } Nie łatwiej przeciążyć? dodaj(int a, int b) { return a + b; } dodaj(double a, double b) { return a + b; } dodaj(klasa a, klasa b) { return a + b; }
Divo, 22 grudnia 2007, 20:39
na 2 stronie powinno byc tak, aby mozna bylo zaobserwowac to przeciazenie CODE "Przeciazenie prz = new Przeciazenie(); long a; long i = 40; int b; int j = 20; a = prz.MojaMetoda(i); b = prz.MojaMetoda(j); System.Console.WriteLine("liczba long czyli 60 : {0} i liczba int czyli 30 : {1}", a, b);"
dobry duszek, 19 lutego 2008, 10:59
Nie przeciąrzenia tylko Przeładowania !!!

ciekawy, 1 marca 2009, 17:10

Dodaj swój komentarz

Zasady publikacji komentarzyZasady publikacji komentarzy

Redakcja CentrumXP.pl nie odpowiada za treść komentarzy publikowanych na stronach Portalu
i zastrzega sobie prawo do usuwania wypowiedzi, które:

  • zawierają słowa wulgarne, obraźliwe, prowokujące i inne naruszające dobre obyczaje;
  • są jedynie próbami reklamowania stron internetowych (spamowanie poprzez umieszczanie linków);
  • przyczyniają się do złamania prawa bądź warunków licencyjnych oprogramowania (cracki, seriale, torrenty itp.);
  • zawierają dane osobowe, teleadresowe, adresy mailowe lub numery GG;
  • merytorycznie nie wnoszą nic do dyskusji lub nie mają związku z tematem komentowanego newsa, artykułu bądź pliku.

Autor:

Komentarz:

Dodaj komentarz