A A A

Klasy abstrakcyjne i interfejsy

Klasa abstrakcyjna jest to klasa której obiekty nie mogą być tworzone,może być natomiast dziedziczona.

Klasa abstrakcyjna może posiadać konstruktor jak i destruktor, mogą być one jednak wywołane tylko przez klasy pochodne.

Klasę abstrakcyjną tworzymy przy pomocy modyfikatora abstract

Dodatkowo klasa abstrakcyjna może posiadać funkcje abstrakcyjne, funkcja taka posiada liste argumentów, jednak nie posiada ciała.

Funkcje abstrakcyjne muszą zostać nadpisane w klasach pochodnych.

Tworzone są one również modyfikatorem abstract


<?php
abstract class Zwierze{
    protected $imie;
    public function __construct( $imie ){
        $this->imie = $imie;
    }
    final public function  podajImie(){
        return $imie;
    }
    abstract public function wydajOdglos();

}
class Slon extends Zwierze{
    public function __construct( $imie ){
        parent::__construct($imie);
    }
    public function wydajOdglos(){
        echo 'Turr-uuu';
    }
}
?>

Stworzyliśmy klase abstrakcyjną Zwierze która posiada konstruktor, jedną funkcje finalną i funkcję abstrakcyjną. Klasa Slon ktora dziedziczy klase abstrakcyjna Zwierze nadpisuje funkcje abstrakcyjna(musi to zrobic), jak i wywoluje konstruktor klasy abstarcyjnej w ciele swojego konstruktora. Nalezey pamietac ze klasa Slon nie moze nadpisac funkcji podajImie.

Interfejsy

Interfejs jest jakby mocnie abstrakcyjną klasą, może mieścić jedynie metody, które z założenia są abstrakcyjne.

Metody w interfejsie są domyślnie abstrakcyjne tak więc, wszystkie metody zawarte w interfejsie muszą zostać nadpisane w klasach pochodnych.

Przy pomocy interfejsów masz możliwość wymuszenia na klasach, aby posiadały niezbędne do współpracy z innymi elementami metody, tak więc intersejsy zapewniają określone cechy klasy.

Interfejs tworzymy słowem kluczowym interface

Klasy nie dziedzicza interfejsów, klasy je implemetują, dokonujemy tego używając modyfikatora implements po którym podajemy nazwy interfejów do zaimplementowania.

Do danej klasy możemy implementować dowoln± ilość interfejsów.

Interfejsy mogą dziedziczyć inne interfejsy.

Interfejsy nie mogą dziedziczyć ani implementować klas.


<?php
interface miesozerne{
    function zjedzMieso($mieso);
}
interface roslinozerne{
    function zjedzWarzywo($warzywo);
}
class Slon implements miesozerne,roslinozerne{
    //rozne wlasciwosci i metody
    function zjedzMieso($mieso){
        echo 'Ja slon zjadam '.$mieso;
    }
    function zjedzWarzywo($warzywo){
        echo 'Ja slon zjadam '.$warzywo;
}
}
interface wszystko extends miesozerne, roslinozerne {

}


?>

Stworzylismy dwa interfejsy, miesozerne i roslinozerne. Interfejsy te posiadają odpowiednio metody zjedzMieso jak i zjedzWarzywo. Tak więc klasy implementujące je muszą te metody nadpisac. Widzimy że klasa Slon implementuje interfejs miesozerne jak i roslinozerne, taki sam efekt moglibysmy otrzymac implementując interfejs wszystkozerne ktory dziedziczy po roslinozerne i miesozerne.

Różnice między klasami abstrakcyjnymi a interfejsami

  • W interfejsach wszystkie metody są abstrakcyjne, natomiast w klasie abstrakcyjnej można stworzyc metody posiadające ciało, jak i abstrakcyjne.
  • W php można dzidziczyć jedynie po jednej klasie, natomiat interfejsów, można implementować wiele. Ponadto interfejsy mogą dziedziczyc wiele interfejów
  • Klasa abstrakcyjna zazwyczaj jest mocno związana z klasami dziedziczącymi w sensie logicznym, czyli np. tworzymy klasę abstrakcyjną Planeta po której dziedziczą konkretne klasy planet (np Ziemia, Mars). Interfejs natomiast nie musi być już tak mocno związany z daną klasą, on określa jej cechy, np możesz stoworzyć interfejs Zniszczalny, który mówi że dany obiekt może zostać zniszczony. Taki interfejs możesz nadać zarówno klasą Planeta, Gwiazda, Budynek itp.

Zadania

Napisz klasę abstrakcyjną Tabela i dziedziczącą po niej klasę TabelaHTML

Cechy klasy Tabela

  • posiada wysokość i szerokość
  • na podstawie wysokości i szerokości tworzy tablicę wielowymiarową o rozmiarach - wysokość na szerokość, wstępnie wszystie elementy posiadają wartość 0
  • posiada abstrakcyjną metodę rysujSie
  • posiada finalną metodą służącą do wpisywania wartości w odpowienim miejscu w tabeli.

Cechy klasy TabelaHTML

  • dodaje ceche - szerokość kolumny
  • nadpisuje metodę rysujSie, rysując tabelę o zadanych rozmiarach, w odpowiednich polach wpisując odpowiednie wartości z tablicy

Podpowiedź - chcąc narysować tabelę o rozmiarach 2 x 3 i szerokości każdej z kolumn 17px użyjemy kodu:


<table>
	<tr>
		<td style="width:17px" >komórka1</td> 
		<td style="width:17px">komórka2</td> 
		<td style="width:17px">komórka3</td>
	</tr>
	<tr> 
		<td style="width:17px">komórka1</td> 
		<td style="width:17px">komórka2</td>
		<td style="width:17px">komórka3/td>
	</tr>
</table>

Pokaż rozwiązanie


<?php
abstract class Tabela
{
protected $wysokosc;
protected $szerokosc;

protected $tablica = array();
protected function __construct($szerokosc, $wysokosc )
{
    $this->szerokoscKomorek = $szerKom;
    $this->szerokosc = $szerokosc;
    $this->wysokosc = $wysokosc;
    
    // tworzymy tymczasową tablicę, będzie ona rozmiaru
    // takiego jak przesłana szerokość
    $tymczasowa = array();
    for($i = 0; $i < $szerokosc; ++$i){
        // do każdego elementu wpisujemy wartość 0
        $tymczasowa[]= 0;
    }

    /* to tutaj tworzyć będziemy naszą 
    tablicę dwuwymiarową,
    tworzymy tablicę o ilości elementów 
    jak przesłana wysokość,
    do każdego elementu dopinamy tablicę tymczasową
    wynikiem tego powstanie tablica o wymiarach:
    $wysokosc x $szerokosc */
    for($j = 0; $j < $wysokosc; ++$j ){
        $this->tablica[] = $tymczasowa; 
    }

}

// abstrakcyjna metoda rysujSie
abstract public function rysujSie();

// finalna metoda wpiszPole, za jej pomocą wpisujemy 
// daną wartość do określonego elementu tablicy
final public function wpiszPole($y, $x, $element){
    $this->tablica[$y][$x] = $element;
}
}

class TabelaHTML extends Tabela
{
protected $szerokoscKomorek;

// w konstruktorze wywołujemy konstruktor rodzica
// po czym ustawiamy szerokoscKomorek
public function __construct(
            $szerokosc, $wysokosc , $szerKom)
{
    parent::__construct($szerokosc, $wysokosc);
    $this->szerokoscKomorek = $szerKom;
}

    /* nadpisana metoda rysujSie, gdyby nasza klasa 
    nie posiadala tej metody, podczas uruchomienia
    nastapilby blad gdyż musimy
    nadpisac metode abstakcyjna */
public function rysujSie()
{
    echo '<table>';
    // glówną pętlą budować będziemy wiersze
    for($i = 0 ; $i < $this->wysokosc; ++$i){
        // tworzymy wiersz
        echo '<tr>';
        // tą petla tworzyc bedziemy kolumny 
        // w poszczegolnym wierszu
        for($j = 0 ; $j < $this->szerokosc; ++$j){
            // tworzymy kolumne o ustalonej szerokosci
            // i wpisujemy w nią daną wartość z tablicy
            echo '<td style="width:
            '.$this->szerokoscKomorek.'px">'.
            $this->tablica[$i][$j]. 
            '</td>';
        }
        
        /* sygnalizujemy koniec wiersza, nastepnie 
        wykonany zostanie kolejny obieg petli, 
        wiec dopisany kolejny wiersz 
        lub zakonczenie petli w wypadku narysowania
        wystarczajacej ilosci wierszy */
        echo '</tr>';
    
    }
    
// konczymy tablice
echo '</table>';    
}

}
?>

«     Test      »