2012-04-07 16 views
20

Perché non è consentito estendere i tratti con le classi in PHP?Estendi i tratti con le classi in PHP?

Ad esempio:

Trait T { } 

Class C use T {} 
/* or */ 
Class C extends T {} 

Esiste un potenziale conflitto per tale sintassi? Io non la penso così.

+0

Come sarebbe 'Classe C usare T {}' essere diverso da quello che abbiamo già (a parte la sintassi leggermente diversa)? – Jon

+0

Sintassi più breve quando voglio estendere alcune classi da una classe base ma usando i tratti. – Meglio

+1

@Meglio: Fallo: 'La classe C estende Base {usa T}'. – hakre

risposta

5

Solo le classi possono essere estese. I tratti sono non classi. Possono essere usati/inclusi dalle classi ma non sono classi. Se pensi che un tratto debba essere esteso allora probabilmente dovrebbe essere una classe, probabilmente astratta, e non una caratteristica.

+0

L'idea qui è per sintassi più breve, non per il modo di estendere effettivamente i tratti. – Meglio

+3

@Meglio: la sintassi non ha lunghezza, quindi non esiste una sintassi più breve. – hakre

+0

Notazione più breve. – Meglio

31

Il manuale PHP così:

Tratti è un meccanismo di riutilizzo del codice in linguaggi successione singoli come PHP. Un tratto ha lo scopo di ridurre alcune limitazioni dell'ereditarietà singola consentendo a uno sviluppatore di riutilizzare insiemi di metodi liberamente in diverse classi indipendenti che vivono in diverse gerarchie di classi. La semantica della combinazione di Tratti e classi è definita in un modo che riduce la complessità ed evita i tipici problemi associati all'ereditarietà multipla e ai Mixin.

Se stai cercando di estendere un tratto, allora dovrebbe probabilmente essere una classe. Se hai una serie di metodi in una classe che vuoi usare in altri, ma sembra inappropriato estendere la classe (ad esempio class Animal extends Vehicle), in PHP 5.4 potrebbe funzionare bene come tratto.

Per rispondere alla domanda in modo più diretto, non è possibile "estendere" un tratto, ma è possibile creare tratti che utilizzano altri tratti. Come per il manuale di PHP:

trait Hello { 
    public function sayHello() { 
     echo 'Hello '; 
    } 
} 

trait World { 
    public function sayWorld() { 
     echo 'World!'; 
    } 
} 

trait HelloWorld { 
    use Hello, World; 
} 

class MyHelloWorld { 
    use HelloWorld; 
} 

Si può considerare che questo è un modo per mantenere i tratti in gruppi logici, e di introdurre qualche modularità.

Modifica: avendo visto alcuni dei commenti, penso che valga la pena notare che l'utilizzo di un tratto in una classe base significa anche che il tratto è in qualsiasi classe che lo estende, e le funzioni del tratto hanno la precedenza sulla classe base ' . Inserirlo nella classe figlio non farebbe che rendere le funzioni del tratto non disponibili alla classe genitore/base.

Parent > Trait > Child 

http://php.net/manual/en/language.oop5.traits.php

11

È possibile estendere tratti un po '. Espandendo la risposta di mrlee, quando si è un tratto di use è possibile rinominare i suoi metodi.

Dire per esempio si ha una caratteristica "padre" che è stato definito dal quadro:

trait FrameworkTrait { 
    public function keepMe() { 
     // Framework's logic that you want to keep 
    } 

    public function replaceMe() { 
     // Framework's logic that you need to overwrite 
    } 
} 

Basta tirare nel tratto genitore, rinominare il suo metodo replaceMe a qualcos'altro, e definire il proprio metodo replaceMe.

trait MyTrait { 
    use FrameworkTrait { 
     FrameworkTrait::replaceMe as frameworkReplaceMe; 
    } 

    public function replaceMe() { 
     // You can even call the "parent" method if you'd like: 
     $this->frameworkReplaceMe(); 

     // Your logic here 
    } 
} 

E poi nella classe:

class MyClass { 
    use MyTrait; 
} 

Ora oggetti di questa classe può fare questo:

$obj = new MyClass(); 

$obj->keepMe();    // calls "parent" trait 
$obj->replaceMe();   // calls "child" trait 
$obj->frameworkReplaceMe(); // calls "parent" trait 
Problemi correlati