2015-10-04 26 views
6

Ho un problema generale con questo caso d'uso: Ho una classe A. Questa classe ha un metodo non astratto doStuffCallback() che potrebbe essere sovrascritto ma non è necessario per ogni sottoclasse. Ma: voglio assicurarmi che se il metodo è sovrascritto, il metodo della sottoclasse deve chiamare il metodo dei genitori.OOP (PHP) - Forza il metodo sovrascritto per chiamare secondo metodo genitore

Esempio:

abstract class A { 
    private function doStuff() { 
     $this->doStuffCallback(); 
    } 

    protected function doStuffCallback() { 
     // IMPORTANT CODE HERE 
    } 
} 

class B extends A { 
    protected function doStuffCallback() { 
     parent::doStuffCallback(); // I want to enforce this because the parents method code is important 

     // ALSO IMPORTANT CODE 
    } 
} 

Poiché il metodo override fa la stessa cosa sarebbe molto brutto per definire due metodi per la stessa responsabilità e un aiutante-metodo privato che chiama entrambi. Così:

abstract class A { 
    private function doStuff() { 
     $this->callDoStuffCallback(); 
    } 

    private function callDoStuffCallback() { 
     $this->internalDoStuffCallback(); 
     $this->doStuffCallback(); 

     // This is VERY ugly 
    } 

    private function internalDoStuffCallback() { 
     // IMPORTANT CODE HERE 
    } 

    protected function doStuffCallback() {} 
} 

class B extends A { 
    protected function doStuffCallback() { 
     // IMPORTANT CODE 
    } 
} 

Questo è davvero brutto e laborioso. Quindi la mia domanda: C'è un modo in PHP per forzare i metodi sovrascritti a chiamare il metodo dei genitori?

risposta

6

No. Non esiste una caratteristica del linguaggio in PHP; questa restrizione non è possibile nella maggior parte dei linguaggi sottotipo -OO.

Invece i programmi devono fare affidamento su contratti di documentazione espliciti; e, si spera, test unitario per garantire la conformità.


protezioni possono anche essere impiegati in modo tale che, ad un certo punto per e quando viene utilizzato un metodo sulla classe genitore, potrebbe un'eccezione se lo 'stato attuale' non è valido (per es. Come e tale metodo non è stato ancora chiamato). Ciò può anche essere reso più esplicito facendo in modo che la sottoclasse richieda di chiamare (come definito nel contratto di documentazione) un metodo speciale, anziché semplicemente il super metodo sovrascritto. Tuttavia, tale è al di fuori di qualsiasi tipo di sistema.

Mentre il self:: portata potrebbe essere utilizzato (es. Chiamare il metodo non overriding che chiama il metodo overriding), ciò comporterebbe maggiori magia per evitare loop ricorsione infinita (ad esempio uno stato stack.); e sarebbe altrettanto facile omettere accidentalmente l'utilizzo.

La mia raccomandazione è di chiamare un metodo (privato) che chiama questo metodo "forse sovrascritto" in relazione a qualsiasi logica si applica, come mostrato nell'esempio (anche se si spera con più nomi di attività specifici). Quindi il metodo sovrascritto (protetto) non è previsto o richiesto per gestire una qualsiasi logica speciale; né è inteso per essere chiamato direttamente al di fuori del contesto stabilito dalla classe genitore - è proprio quello che pretende di essere, un callback speciale.

+0

Grazie per la tua risposta! Penso esattamente la stessa cosa. Credo che l'OOP che usiamo oggigiorno non sia ancora completo. Sono rimasti così tanti aspetti che sono importanti ma non gestiti. –

-2

No, è possibile accedere, è possibile utilizzare il metodo per il genitore, come questo

<?php 

class A { 

    function s1($p1) { 
     echo 's1: '.$p1; 
    } 
} 


class B extends A { 

    public function callParent($method, $p1) { 
     parent::$method($p1); 
    } 
} 


$b = new B(); 

$b->callParent('s1', 'param1'); 

o sostituire estende su metodi magici __call ed ecc https://github.com/StagnantIce/php_extend_magic/blob/master/AExtendClass.php

+0

Come questo risolve il mio problema? Penso che questa sia una soluzione meno intelligente del semplice aspettarsi che la sottoclasse faccia la giusta implementazione con la documentazione (chiamate il metodo genitore quando si esegue l'override). Voglio dire, i tuoi esempi richiedono che OGNI CLIENTE della classe e non solo la classe implementata stessa chiamino il metodo genitore in senso riflessivo. Questo è l'approccio più intuitivo e insicuro che abbia mai visto. Senza offesa :) –

2

Tendo a non essere d'accordo con "Questo è MOLTO brutto". È il modo standard di gestire questo caso d'uso e una variante di Template Method Pattern.

Ora sto solo supponendo perché non hai fornito un esempio reale, ma se dici che i due metodi "fanno la stessa cosa", potrebbe esserci qualcosa di sbagliato nel tuo progetto. Se fanno la stessa cosa, perché è necessaria l'implementazione genitore se la sottoclasse fa la stessa cosa in un modo diverso?A me sembra che il metodo faccia effettivamente più di una cosa e tu possa essere in grado di scomporlo in più parti che possono essere sovrascritte individualmente (o meno, quindi renderle private o definitive).

+0

Sì, "la stessa cosa" non è il termine corretto qui. Questi metodi hanno la stessa responsabilità ma il metodo sottoclasse lo estende per i propri requisiti aggiuntivi. –