OOP - Clase abstract si interface

Abstract si Interface (interfata) sunt tipuri de clase mai speciale in OOP, pentru lucru mai avansat in programarea orientata pe obiecte.

1. Clase si Metode abstract

Clasele abstracte se declara folosind cuvantul abstract inaintea lui "class".
La aceste tipuri de clase nu se poate crea instanta de obiect, ele pot fi doar mostenite de alte clase extinse din ele.
In clasele abstracte se definesc si metode abstracte, acestea se declara cu acelasi cuvant "abstract" si fara corpul de acolade, doar numele si parantezele rotunde, cu parametri necesari.
- Iata un exemplu de clasa cu o proprietate "protected" o metoda abstracta si una accesor:

<?php
// Definire clasa abstracta
abstract class Fructe {
  protected $color;        // Proprietate

  // Definire metoda abstracta
  abstract function Stoc($luna);

  // Metoda accesor pt. "color"
  public function setColor($c) { $this->color = $c; }
}
?>
- Daca se creaza o instanta de obiect la aceasta clasa (de ex.: $obj = new Fructe();), va genera eroare de genul:
Fatal error: Cannot instantiate abstract class
- Metodele abstracte se creaza doar in clase abstracte.
- Rolul claselor si metodelor abstracte este acela de a crea un model minim de metode obligatorii care trebuie definite in sub-clase normale derivate din ele (cu extends). Metodele abstracte definite in cea parinte trebuie create in orice clasa copil extinsa din cea abstracta, cu acelasi numar de parametri (numele poate fi difereit).
De ex., orice sub-clasa extinsa din clasa Fructe (definita mai sus) trebuie sa contina metoda Stoc() cu un parametru, cum ar fi cea din urmatorul exemplu, denumita Mere.
<?php
// Definire clasa copil, extinsa din cea abstracta
class Mere extends Fructe {
  private $kg;        // Proprietate

  // Metoda obligatorie (seteaza valoarea proprietatii "Kg")
  public function Stoc($kg) {
    $this->kg = $kg;
  }

  // Alta Metoda - optionala (returneaza valoarea proprietatii "kg")
  public function getKg() {
    return $this->kg. ' kg';
  }
}
?>
- Deoarece clasa Mere extinde Fructe, trebuie sa contina, pe langa alte elemente, si metodele abstracte declarate in aceea (anume Stoc(), cu un parametru). Daca aceasta sub-clasa nu ar avea metoda Stoc(), va genera eroare de genul:
Fatal error: Class Fructe contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Mere::Stoc) in...
- Sub-clasele care extind o clasa abstracta pot fi utilizate normal, se pot crea si folosi instante de obiect la ele, mostenesc si pot folosi elementele cu atribut "public" si "protected" din cea parinte.
De exemplu:
<?php
// Creare instanta de obiect la clasa Mere si apelare metode
$obj = new Mere();
$obj->Stoc(78);
echo $obj->getKg();        // Afiseaza:  78 kg
?>

2. Interfaces

Ca rol, se poate spune ca Interface este asemanatoare cu clasa "abstract".
Clasa Interface este folosita ca tipar, sau template pentru clase cu functii similare, care trebuie sa respecte o anumita structura de metode.
Sintetizat, Interface este o clasa cu o lista de metode obligatorii ce trebuie sa fie create in clasele unde este implementata. Toate metodele specificate in "Interface" sunt cu atribut public si trebuie sa fie definite in clasele in care e aplicata, avand acelasi numar de parametri cati sunt indicati in "Interface".

Creare interface

Clasa interface se creaza similar cu celelalte tipuri de clase. Diferenta e aceea ca la definirea ei, in loc de cuvantul "class" se foloseste cuvantul "interface"; in plus, in corpul ei se scrie doar o lista cu metode publice fara, alt cod.
Sintaxa generala este urmatoarea:

- La declararea metodelor in Interface nu se adauga acoladele sau codul lor, si nici alt atribut diferit de "public".

Iata un exemplu cu o Interface, denumita "ITest", in care sunt definite 2 metode: "Links()" si "Tutoriale()".
<?php
// Definire Interface ITest
interface ITest {
  // Lista cu metode
  public function Links();
  public function Tutoriale($str, $nota);
}
?>

Implementare interface

Dupa ce a fost definit tiparul "interface", se pot crea clase care implementeaza metodele stabilite in acel tipar, respectand si numarul de parametri.
Implementarea se face adaugand cuvantul implements si numele Interfatei la definirea claselor, dupa numele lor.
                class NumeClasa implements numeInterfata {
                    // Instructiuni
                }

Acestea trebuie sa contina in corpul lor toate metodele definite in "interface", cu atribut "public", si numarul de parametri stabiliti pt. fiecare (numele la parametri poate fi diferit). Pe langa acestea pot contine si alte metode.


Iata un exemplu cu o clasa care implementeaza interfata ITest creata mai sus.
<?php
// Creare clasa care aplica Interfata ITest
class WebDevelopment implements ITest {
  // Definire proprietate 'link' (cu atribut "protected")
  protected $link = 'www.marplo.net';

    /* Definire metodele obligatorii (Links si Tutoriale), din interface */

  // Returneaza valoarea proprietatii 'site'
  public function Links() {
    return $this->link;
  }

  // Returneaza valoarea unei variabile din ea ($re), ce preia argumentele transmise
  public function Tutoriale($gen, $nota) {
    $re = $gen. '-'. $nota;
    return $re;
  }

  // Se pot crea si alte metode, suplimentare
  // Aceasta modifica valoare proprietatii "link"
  public function setLink($link) {
    $this->link = $link;
  }
}
?>
- Metodele obligatorii (aici "Links()" si "Tutoriale()") respecta exact numarul de parametri stabiliti in "interface" "ITest". Alte metode (aici "setLink()") si proprietati sunt optionale, in functie de rolul fiecarei clase.
- Numele parametrilor nu conteaza (observati ca in loc de $str s-a folosit $gen), dar numarul lor trebuie sa fie aceleasi ca in "interface".
- Daca vreuna din conditii nu ar fi respectata in clasa, cum ar fi: nedefinirea unei metode, adaugarea de parametru in plus sau minus; scriptul genereaza eroare.
Astfel, implementarea de "interface" este utila mai ales cand sunt create mai multe clase cu roluri similare si dorim ca acestea sa aibe toate o anumita ordonare si structura minima de metode, mai usor de retinut.

3. Interface ca tip de date

Interfata poate fi utilizata si ca tip de data la parametri de functii, astfel, acel parametru poate fi utilizat ca instanta de obiect la orice clasa din cele ce folosesc acea "interface".
Se intelege mai bine din urmatorul exemplu, in care e creata si folosita inca o clasa (LimbiStraine) ce aplica Tiparul din "ITest"; contine o proprietate si metodele obligatorii stabilite.

<?php
// Creare clasa care aplica Interfata ITest
class LimbiStraine implements ITest {
  // Definire proprietate
  protected $adr = 'www.marplo.net/';

          /* Definire metodele obligatorii (Links si Tutoriale), din interface */

  // Returneaza expresia 'Cale buna'
  public function Links() {
      return'Cale buna';
  }

  // Returneaza valoarea unei variabile din ea (re), ce preia argumentele "nr", "gen" si proprietatea "adr"
  public function Tutoriale($gen, $nr) {
    $re = $nr.'-'. $this->adr. $gen;
    return $re;
  }
}
?>
Intr-un script PHP se scrie urmatorul cod:
<?php
// Se includ fisierele cu clasele create mai sus (daca sunt in fisiere externe): ITest (Interfata), WebDevelopment si LimbiStraine
include('interf.ITest.php');       // Interface
include('class.WebDevelopment.php');
include('class.LimbiStraine.php');

// Creare functie care accepta doar argument cu obiect la clasele care au implementata Interfata "ITest"
function cursuri(ITest $obj) {
  // Apeleaza metodele comune (stabilite in ITest) prin parametru $obj
  echo '<br />'. $obj->Links();
  echo '<br />'. $obj->Tutoriale('php-mysql', 4);
}

// Creare instante de obiect la clasele folosite
$web_development = new WebDevelopment();
$limbi_straine = new LimbiStraine();

// Apeleaza functia cu instantele de obiect ale claselor ce au aplicat ITest
cursuri($web_development);        // "www.marplo.net" si "php-mysql-4"
cursuri($limbi_straine);          // "Cale buna" si "4-www.marplo.net/php-mysql"
?>
- Functia "cursuri()" creata cu aceasta formula intre acolade "function cursuri(ITest $obj)" face ca ea sa accepte ca argument doar obiect care are implementat "ITest".
- Observati ca apeland functia cu argumente diferite, reprezentand numele instantelor la clase, foloseste parametru $obj ca instanta la clasa respectiva, si poate apela aceleasi metodele ("Links()" si "Tutoriale()") pt. fiecare deoarece aceste fiind specificate in "interface" ele trebuie sa existe in fiecare clasa ce apartine acelei Interfate, cu acelasi numar de parametri.
- Prin aceasta tehnica nu mai e nevoie de a crea aceeasi functie pt. fiecare instanta.
Acest exemplu va afisa in browser urmatorul rezultat:
www.marplo.net
php-mysql-4
Cale buna
4-www.marplo.net/php-mysql
Metode magice __get, __set, ... <<-- Anterior ----------- Urmator -->> Functii cu Parametri object ...

Un Test simplu in fiecare zi

HTML
CSS
JavaScript
PHP-MySQL
Engleza
Spaniola
Care tag se foloseste in <table> pentru a crea celula de tip "header"?
<thead> <th> <td>
<table><tr>
  <th>Title 1</th>
  <th>Title 2</th>
</tr></table>
Ce proprietate CSS seteaza distanta dintre randuri?
line-height word-spacing margin
.some_class {
  line-height: 150%;
}
Care functie deschide o noua fereastra.
alert() confirm() open()
document.getElementById("id_button").onclick = function(){
  window.open("http://coursesweb.net/");
}
Indicati functia PHP care returneaza un array cu numele fisierelor si directoarelor dintr-un director.
mkdir() scandir() readdir()
$ar_dir = scandir("dir_name");
var_export($ar_dir);
Care din urmatoarele forme a verbului "sleep" (a dormi) se foloseste pentru viitor?
sleeping slept will sleep
He will sleep there.
- El va dormi acolo.
Care din urmatoarele forme a verbului "dormir" (a dormi) se foloseste pentru viitor?
dormido dormirá durmiendo
Él dormirá allí.
- El va dormi acolo.
OOP - Clase abstract si interface - Tutorial PHP