Estendi la classe o crea un'istanza?

3

Sto leggendo Pro PHP e jQuery e voglio ricostruire l'esempio. L'autore sta creando una classe di connessione al database:

class DB_Connect {

protected $db;

protected function __construct($dbo = NULL){
     if (is_object($db)) {
          $this->db = $db;
     }
     else {
          // Constants are defined in /sys/config/db-cred.inc.php
          $dsn = "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME;
          try {
              $this->db = new PDO($dsn, DB_USER, DB_PASS);
          }
          catch (Exception $e) {
              die ($e->getMessage());
          }
     }
} 

Questa classe viene quindi estesa dalla classe principale dell'applicazione, per ottenere l'accesso all'oggetto del database.

Perché questo è fatto in questo modo? Non potremmo piuttosto creare un'istanza di DB_Connect nella classe principale? Quali sono i vantaggi di questo approccio?

    
posta Sprottenwels 10.06.2013 - 13:34
fonte

2 risposte

9

Quello che vedi è un classico errore da principiante, che stabilisce un è-a relazione (creazione di una sottoclasse) tra due classi quando la relazione effettiva è ha-a (istanziazione di una classe come membro). È un peccato che questo errore sia stato stampato.

Se lo scopo dichiarato di Main è vero, il suo scopo è di essere un modulo centrale per un'applicazione. Non è, in sé e per sé, qualcosa che stabilisce una connessione al database e non è possibile creare un'istanza di Main per farlo. Il semplice test per questo è quello di dire ad alta voce le due alternative e vedere quali anelli sono veri. Ad esempio:

  • "A Car è a Wheel " (sottoclasse) non ha senso, perché le auto non sono ruote. Se dovessi modellare macchine a quattro e tre ruote, dovresti disegnare un vuoto completo su come farlo con la sottoclasse.

  • "A Car ha una Wheel " (istanziazione) funziona perché le macchine sono composte (tra le altre cose) da una o più ruote. Immaginare un FourWheeledCar e un ThreeWheeledCar contenente più istanze di Wheel sarebbe facile: una classe ha quattro istanze di Wheel e l'altra ha tre.

risposta data 10.06.2013 - 14:39
fonte
4

Non direi che è un buon progetto estendere la classe principale dell'applicazione da DB_Connect per i seguenti motivi:

  1. L'ereditarietà deve essere utilizzata solo se la sottoclasse può essere utilizzata in modo comportamentale uguale alla Superclasse, il che non è il caso nel tuo esempio (vedi Principio di sostituzione di Liskov )
  2. Poiché LSP viene violato e un DB proviene da un punto di vista comportamentale utilizzato dalla classe Main, è un caso di utilizzo classico per Composition, ovvero creando un'istanza di DB_Connect nella classe Main come suggerito.

Il tuo problema è un problema di progettazione comune e viene affrontato nel principio di progettazione "Composizione sull'ereditarietà" .

    
risposta data 10.06.2013 - 14:32
fonte

Leggi altre domande sui tag