Artykuł

lut 17 2009
0

Programowanie obiektowe - polimorfizm

W dzisiejszym artykule zajmiemy się polimorfizmem. Polimorfizm jest ostatnim z filarów paradygmatu programowania obiektowego i jest szczególnie przydatny gdy chcemy utworzyć szereg klas według określonego schematu. Z pojęciem polimorfizmu ściśle związana jest definicja interfejsu. Wszystkie przytoczone powyżej terminy zostaną opisane w niniejszym artykule. Przed przystąpieniem do lektury niniejszego artykułu zachęcam do przeczytania poprzednich części (szczególnie artykułu poświęconego dziedziczeniu).

Polimorfizm - wprowadzenie i definicja interfejsu

Aby zdefiniować pojęcie polimorfizmu, niezbędna okaże się wiedza na temat dziedziczenia (przedstawiona w poprzednim artykule) oraz interfejsów. Jak zapewne pamiętacie, klasy możemy dziedziczyć inaczej mówiąc rozszerzać. Kiedy tworzymy nowe klasy, które opierają się na dziedziczeniu, to nowo tworzona klasa posiada wszystkie elementy swojego przodka (zmienne, metody). Naraz możemy dziedziczyć tylko jedną klasę (obojętnie czy jest to klasa abstrakcyjna czy też zwykła klasa). Stanowi to pewne ograniczenie. Dlatego programiści wprowadzili inną interesującą strukturę jaką jest interfejs. Interfejs pozwala na tworzenie szkieletu czegoś co kształtem przypomina klasę. Jednak również tu występują restrykcje. W interfejsie możemy tworzyć tylko stałe oraz nagłówki metod (typ zwracany, nazwa, parametry). Interfejsy należy jednak stosować z rozwagą. Implementując dowolny interfejs w danej klasie, musimy wypełnić go całkowicie treścią (wypełnić treścią wszystkie nagłówki metod).

Wiele osób często myli interfejsy z klasami abstrakcyjnymi, dlatego warto wypunktować różnice i podobieństwa między tymi strukturami:

  • W interfejsie tworzymy stałe i nagłówki metod. W klasach abstrakcyjnych możemy tworzyć dowolne struktury.
  • Każda klasa może implementować wiele interfejsów, ale dziedziczyć tylko z jednej klasy.
  • Interfejsy mogą również się dziedziczyć wzajemnie, jednakże w przeciwieństwie do klas, jeden interfejs może dziedziczyć kilka innych naraz (nazwy interfejsów separujemy przecinkiem).
  • Zarówno interfejsy jak i klasy abstrakcyjne nie mogą stanowić samodzielnych bytów. Dlatego muszą być zaimplementowane/dziedziczone w normalnej klasie.

Ponieważ posiadamy definicję interfejsu, czas wrócić do polimorfizmu. Czym jest więc ten polimorfizm? Definicja mówi: Polimorfizm to cecha dzięki której jeden interfejs może być stosowany do wykonania różnych zadań. Przekładając to na bardziej ludzki język: w interfejsie tworzymy strukturę, która będzie wykorzystywana w różnych klasach, w zależności od potrzeb dostosowana do sytuacji. O tym jakie interfejsy mają znaczenie w praktyce przekonamy się w następnym akapicie.

Interfejsy w praktyce

Aby prześledzić działanie interfejsów wykorzystamy przykład zwierzęcy. Zbudujemy interfejs zawierający metodę makeSound. Następnie zaimplementujemy go w klasie Kota i Psa wypełniając metodę makeSound stosowną treścią. Na podstawie interfejsów A, B, C, prześledzimy również proces dziedziczenia interfejsów.

Interfejsy w PHP

Ponieważ wszystkie najważniejsze informacje zostały już przedstawione, przejdźmy od razu do konkretów:

interface Animal
{
	function makeSound();
}

class Cat implements Animal
{
	function makeSound() 
	{
		echo 'Miaaaaaaaał';
	}
}

class Dog implements Animal
{
	function makeSound()
	{
		echo 'Haaaaaaaauł';
	}
}

Przejdźmy do interpretacji. W liniach od 1-4 do znajduje się implementacja interfejsu Animal. Do tworzenia interfejsów używamy słowa kluczowego interface. W PHP wszystkie elementy interfejsów są domyślnie publiczne i w tym wypadku nie można używać modyfikatorów dostępu. W liniach od 6 do 20 tworzymy klasy Cat i Dog. Obie implementują interfejs Animal i wypełniają stosowną treścią metodę makeSound(), której implementacja została wymuszona po załadowaniu wskazanego interfejsu.

Na kolejnym listingu prześledzimy proces dziedziczenia interfejsów:

interface A
{
	function ATest();	
}

interface B
{
	function BTest();	
}

interface C extends A, B
{
	// posiada już nagłówki metod ATest i BTest
	function CTest();
	const test = 'Stała test zdefiniowana jest na pokaz';
}

Na początku tworzymy interfejs A, który zawiera nagłówek metody ATest. W kolejnym kroku tworzymy interfejs B, z analogiczną metodą BTest. W ostatnim kroku tworzymy interfejs C. Dziedziczy on zawartość dwóch poprzednich interfejsów. Ponadto, tworzy nowy nagłówek metody C i definiuje stałą tekstową test. Dzięki dziedziczeniu, by skorzystać z wszystkich trzech interfejsów wystarczy, że do docelowej klasy zaimplementujemy interfejs C.

Interfejsy w Javie

Polecenia dotyczące tworzenia interfejsów są bardzo podobne do tych, które przedstawiono przy okazji interfejsów w PHP. Różnice dotyczą jedynie semantyki języka, która jest odrobinę inna w Javie. Czas na przykłady praktyczne:

interface Animal
{
	void makeSound();  
}

class Cat implements Animal
{
	public void makeSound() 
	{
		System.out.println("Miaaaaaaaał");
	}
}

class Dog implements Animal
{
	public void makeSound()
	{
		System.out.println("Haaaaaaaauł");		
	}
}

Przykład analogiczny jak w PHP. Przejdźmy do interpretacji. W liniach 1-4 tworzymy interfejs Animal. Java w odróżnieniu do PHP pozwala na używanie tutaj modyfikatorów dostępu, z reguły jednak używamy modyfikatora public, lub po prostu stosujemy modyfikator domyślny. W liniach od 6 do 20 tworzymy klasy Kota i Psa implementując metodę makeSound zadeklarowaną w interfejsie.

Prześledźmy również jeszcze proces dziedziczenia interfejsów, który został przedstawiony na poniższym listingu:

interface A
{
	void ATest();	
}

interface B
{
	void BTest();	
}

interface C extends A, B
{
	// posiada już nagłówki metod ATest i BTest
	void CTest();
	final String test = "Stała test zdefiniowana jest na pokaz";
}

Na początku tworzymy interfejs A z nagłówkiem metody ATest, następnie analogiczny interfejs B z nagłówkiem metody BTest. W ostatnim kroku tworzymy interfejs C, który dziedziczy właściwości obu wcześniej utworzonych interfejsów. Ponadto, tworzymy tutaj nagłówek nowej metody: CTest i deklarujemy stałą test. Prawda, że proste?

Podsumowanie

Polimorfizm, jest ostatnim z trzech głównych paradygmatów programowania obiektowego. Jego zastosowanie najbardziej odpowiednie wydaje się w dużych projektach, kiedy w jakiś sposób chcemy wymusić implementację określonych metod części pisanych przez nas klas. Definiując interfejs, mamy pewność, że nigdy nie nastąpi żadne przeoczenie, ponieważ błędny kod nie da się skompilować (java) / wykonać (php).

Artykuł poświęcony polimorfizmowi, był ostatnim z cyklu programowanie obiektowe. Zachęcam do czytania innych artykułów umieszczanych na stronie.

Data ostatniej modyfikacji: 27.10.2012, 22:46.

Podoba Ci się ten wpis? Powiedz o tym innym!

Send to Kindle

Komentarze

blog comments powered by Disqus