04. Przeciążanie metod i konstruktorów

04. Przeciążanie metod i konstruktorów

Autor: Paweł Kruczkowski

Opublikowano: 10/17/2006, 12:00 AM

Liczba odsłon: 91819

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.

Jak wykorzystać Copilot w codziennej pracy? Kurs w przedsprzedaży
Jak wykorzystać Copilot w codziennej pracy? Kurs w przedsprzedaży

Wydarzenia