Abstract Classes vs. Interfaces

Sunt curios: doar eu am avut probleme în a digera și înțelege cum funcționează interfețele, cu ce diferă de clasele abstracte, când se folosesc și de ce?

tl:dr: An interface annotates a usage aspect of a type / class. Do not just extract interfaces from classes. Use abstract classes, when defining a base type.

1 Like

Probabil cel mai simplu ar fi sa pun diferentele dintre cele doua:
1 - poti extinde doar o clasa abstracta, dar poti implementa mai multe interfete
2 - trebuie sa definesti toate metodele dintr-o interfata, dar la clasele abstracte doar metodele abstracte
3 - metodele dintr-o interfata trebuiesc sa fie toate publice, pe cand metodele abstracte nu pot fi private

2 Likes

Clasele abstracte pentru mosteniri si interfetele pentru compozitii. :slight_smile:

1 Like

Interfetele au fost introduse pentru mostenire multipla, de exemplu in C++ poti mosteni doua clase dar poate aparea efectul de diamant http://www.programmerinterview.com/index.php/c-cplusplus/diamond-problem/

@iamntz, clasele abstracte din ce stiu eu pot contine metode care se mostenesc si pot fi doar extinse, la fel ca interfetele.
In schimb, interfetele contin doar niste metode sau variabile mandatory la extindere insa nu poti prelua in clasa extinsa instructiunile date unei metode in interfata. De exemplu:

abstract class mainPayment {
    public function getPayment(){
        // instructiunile lui getPayment
    }
}

class buonPayment extends mainPayment {
    public function __construct(){
        $this->getPayment();
    }
}

In cazul de fata ai putut folosi metoda getPayment() definita in clasa abstracta. Daca era definita intr-o interfata, nu o puteai folosi ci trebuia redefinita in clasa care a implementat-o.

Ok, am impresia că s-a înțeles că nu știu acum la ce folosesc interfețele vs abstractele. În final am priceput, dar am avut nevoie de ceva timp pentru a procesa, până să facă acel „click”, când totul are sens :smile:

@adavidoaiei: interfețele nu au legătură cu moștenirile, cel puțin nu în PHP, unde o interfață conține doar semnăturile metodelor, fără nici un fel de cod.

Eu am priceput (și folosesc) interfețele pentru a fi sigur că o clasă implementează anumite metode.

De exemplu, la proiectul curent, am următoarea interfață:

interface FieldInterface {
  public function getField();
}

Iar o metodă dintr-o altă clasă acceptă doar implementări ale acestei interfețe, astfel încât să nu mai verific dacă metoda getField există, dacă parametri sunt OK șamd:


class FieldsGroup
{
  public function addField(FieldInterface $field)
  {
    $field->getField();
  }
}

Evident, $field este definit cam așa:

class Field implements FieldInterface {
  public function getField()
  {}
}

Partea cu adevărat interesantă vine acum: eu pot trimite în FieldsGroup orice clasă cât timp este o implementare a FieldInterface. Și chiar așa fac, pentru că Field este doar pentru exemplul de mai sus. În proiect am, de fapt: Select, Textarea etc (să zicem că e un generator de formulare).

Altfel spus, Design by contract.


Comparativ, abstractele sunt clase propriu-zise ce nu pot fi instanțiate, pot fi doar extinse. Pot implementa logică, pot conține și metode abstrace (ce vor fi obligatoriu de implementat de clasa ce o va extinde) șamd.

Din punctul meu de vedere (și din scurta mea experiență OOP) este greșit să folosești o abstractă pentru un Contract.

@iamntz exemplul dat de tine il inteleg si cam asta e logica, poti sa interschimbi doua clase trimise ca parametru atat timp cat implementeaza aceias interfata, exemplele date de mine erau mai basic.

1 Like

Use duck typing maybe with some exceptions sprinkled here and there and just drop both of the Java-ish constructs :sunny:

Mie mi-a picat fisa după ce am făcut vreo două implementări / exemple de Dependency Inversion Principle versus Template Design Pattern.

1 Like

Dincolo de ce s-a spus deja, evită clasele abstracte.

Clasele abstracte sunt atractive cât timp nu ai digerat SOLID. Dup-aia îți dai seama de niște lucruri:

  • ierarhiile adânci de clase fac un sistem greu de înțeles
  • SOLID și prefer composition over inheritance merg mână-n mână

Preferă mereu crearea unei interfețe și a unei implementări, mai ales când faci TDD. Introdu clase abstracte abia când TDD-ul îți va șopti să o faci - TDD îți spune asta, dar trebuie să înveți să asculți ce are de zis.

“The TDD Whisperer” - a new book by Addison-Wesley Professional :sunny:

being serious:

Au sens in limbajele orientate spre OOP (nu, nu este o greseala) verbose, unde ratio intre programatori juniori si non-juniori este >= 1.