Java przeciążanie metod

12 03 2009

Przeciążanie metody umożliwia powtórne użycie tej samej nazwy metody.  Dzięki temu nie musimy tworzyć za każdym razem innej nazwy dla metody, widać to doskonale na przykładzie Klasy String, która posiada metodę statyczną valueOf( <<typ>> ), napisaną w kilku wersjach dla różnych typów danych, jako argumenty:

String.valueOf( boolean b );
String.valueOf( char c );
String.valueOf( char[] data );
String.valueOf( double d );
String.valueOf( float f );
String.valueOf( int i );
String.valueOf( long l );
String.valueOf( Object o );
String.valueOf( char[] data, int offset, int count );

Metoda valueOf( <<typ>> ), została przeciążona w klasie String, jej nazwa pozostała nie zmieniona, lecz parametry w każdej z nich są inne, taki jest bowiem podstawowy warunek na to, aby móc przeciążyć metodę, musi ona różnić się listą parametrów (ich ilością, lub typem).

Zasady przeciążania metod:

  • Lista argumentów musi być różna od tej z metody jaką chcemy przeciążyć, może różnić się ilością, typem parametrów, lub ilością i typem jednocześnie. Jeżeli natomiast nazwa metody oraz jej parametry będą takie same, jak w oryginale, będziemy mieć do czynienia z przesłonięciem metody (jeżeli sytuacja ma miejsce w sub klasie), lub błędem (jeżeli sytuacja ma miejsce w tej samej klasie w której znajduje się metoda, jaką przesłaniamy),
  • Typ zwracany przez metodę przeciążoną, oraz jej specyfikator dostępu, mogą być inne niż w oryginale,
  • Metody przeciążone mogą deklarować nowe wyjątki, lub poszerzać te, które są już zadeklarowane, pod warunkiem, że dziedziczą one po klasie Exception,
  • Metoda może zostać przeciążona w ramach tej samej klasy, lub sub klasy,
  • Typ referencji determinuje, która przeciążona metoda zostanie wywołana.

Ostatni punkt domaga się komentarza. W przypadku metod przesłanianych, o tym, która zostanie wykonana, decyduje typ obiektu, na jaki pokazuje referencja. W przypadku metod przeciążanych, odpowiednia metoda wybierana jest na podstawie typu referencji, a nie obiektu.

Wywołania polimorficzne

Podczas wywoływania metod przeciążonych (w przeciwieństwie do metod przesłoniętych), polimorfizm nie odgrywa żadnej roli, wywoływana jest ta metoda, jaką wskaże typ referencji. Co natomiast stanie się, gdy metoda jest zarówno przeciążona, jak i przesłonięta ?

class A {
    void write(){
        System.out.println( "oryginał" );
    }
}

class B extends A {
    void write(){
        System.out.println( "przesłonięta" );
    }
    void write( String s ){
        System.out.println( "przeciążona" );
    }
}

class Main {
    public static void main( String[] args ) {
        A a = new A();
        B b = new B();
        A ab = new B();

        a.write(); 		// (1) oryginał
        b.write(); 		// (2) przesłonięta
        ab.write(); 		// (3) przesłonięta
        b.write( "xx" ); 	// (4) przeciążona
        a.write( "xx" ); 	// (5) błąd kompilacji
        ab.write( "xx" );       // (6) błąd kompilacji
    }
}

Cała magia dzieje się już podczas wykonywania programu, tzw. wywołania dynamiczne. Chodzi o to że środowisko w jakim uruchomiony jest program sprawdza na bieżąco (przed wykonaniem jakiejkolwiek operacji) jakiego faktycznie typu jest obiekt wskazywany przez referencję. Od tego zależy jaka metoda zostanie wykonana.

  1. Referencja pokazuje na obiekt typu A, więc zostanie wykonana metoda write() z klasy A.
  2. Referencja pokazuje na obiekt typu B, więc zostanie wykonana metoda write() z klasy B.
  3. Referencja pokazuje na obiekt typu B, więc zostanie wykonana metoda write() z klasy B.
  4. Referencja pokazuje na obiekt typu B, wiec zostanie wykonana metoda write (String s) z klasy B.
  5. Błąd kompilacji. Referencja pokazuje na obiekt typu A, klasa ta nie posiada metody write przyjmującej parametr typu String.
  6. Błąd kompilacji. Referencja typu A nie posiada metody write(String s).

Działania

Information

3 Komentarze

4 09 2012
Rafał Podhajny

Typ referencji definiuje metody które można na obiekcie wykonać. Klasa A posiada tylko jedną, bezparametrową metodę write(), dlatego pomimo że do referencji przypisany jest obiekt klasy B (który posiada metodę write(String s)), do dyspozycji oddana jest tylko metoda write() z klasy A. Gdyby klasa B posiadała metodę write(String s)) zostałaby ona wykonana ponieważ przesłaniałaby metodę klasy nadrzędnej.

4 09 2012
Patrycja

Czy w 6 przypadku nie powinno zostać wyświetlone „przeciążona”? Przecież ab.write(„xx”); wskazuje na obiekt typu B, gdzie jest metoda przyjmująca typ String? Proszę o odpowiedź. Pozdrawiam

31 03 2012
Anonim

dobry artykuł

Dodaj komentarz