2012-04-29 11 views
33

Ho notato che non è possibile avere costanti astratte in PHP.Costanti astratte in PHP - Forza una classe figlio a definire una costante

Esiste un modo per forzare una classe figlia a definire una costante (che devo utilizzare in uno dei metodi interni della classe astratta)?

+0

Una costante è piena portata volta impostato il relativo disponibile in ogni classe, metodo o funzione what-not. non ha senso, si prega di fornire un codice per spiegare un po 'di più. –

+2

Definire una costante nella classe astratta (quindi ogni classe figlio ha una costante, anche se non definisce la sua), o usa una funzione astratta (che costringe ogni classe figlia a definirne la propria). Modifica: la risposta breve alla tua domanda è no. – halfer

risposta

25

A constant è un constant; Non v'è alcun abstract o private costanti in PHP per quanto ne so, tuttavia è possibile un lavoro intorno:

esempio Abstract Classe

abstract class Hello { 
    const CONSTANT_1 = 'abstract'; // Make Abstract 
    const CONSTANT_2 = 'abstract'; // Make Abstract 
    const CONSTANT_3 = 'Hello World'; // Normal Constant 
    function __construct() { 
     Enforcer::__add(__CLASS__, get_called_class()); 
    } 
} 

Questo sarebbe funzionare bene

class Foo extends Hello { 
    const CONSTANT_1 = 'HELLO_A'; 
    const CONSTANT_2 = 'HELLO_B'; 
} 
new Foo(); 

Bar restituisce l'errore

class Bar extends Hello { 
    const CONSTANT_1 = 'BAR_A'; 
} 
new Bar(); 

Songo sarebbero tornati errore

class Songo extends Hello { 

} 
new Songo(); 

Enforcer Classe

class Enforcer { 
    public static function __add($class, $c) { 
     $reflection = new ReflectionClass($class); 
     $constantsForced = $reflection->getConstants(); 
     foreach ($constantsForced as $constant => $value) { 
      if (constant("$c::$constant") == "abstract") { 
       throw new Exception("Undefined $constant in " . (string) $c); 
      } 
     } 
    } 
} 
+2

Questa non è una costante, è una funzione. – Zombaya

+0

@Zombaya grazie per l'osservazione .. ho cliccato su invio troppo presto .. spero che tu possa prendere in considerazione il down vote adesso .. grazie ... – Baba

+6

:) Riconsiderò, ho un upvote invece. – Zombaya

6

No, ma si potrebbe provare altri modi, come metodi astratti:

abstract class Fruit 
{ 
    abstract function getName(); 
    abstract function getColor(); 

    public function printInfo() 
    { 
     echo "The {$this->getName()} is {$this->getColor()}"; 
    } 
} 

class Apple extends Fruit 
{ 
    function getName() { return 'apple'; } 
    function getColor() { return 'red'; } 

    //other apple methods 
} 

class Banana extends Fruit 
{ 
    function getName() { return 'banana'; } 
    function getColor() { return 'yellow'; } 

    //other banana methods 
} 

o membri statici:

abstract class Fruit 
{ 
    protected static $name; 
    protected static $color; 

    public function printInfo() 
    { 
     echo "The {static::$name} is {static::$color}"; 
    } 
} 

class Apple extends Fruit 
{ 
    protected static $name = 'apple'; 
    protected static $color = 'red'; 

    //other apple methods 
} 

class Banana extends Fruit 
{ 
    protected static $name = 'banana'; 
    protected static $color = 'yellow'; 

    //other banana methods 
} 

Source

+3

Se copi il codice da un'altra posizione sul Web, assicurati di citare anche la fonte. Il codice precedente è stato preso da http://www.sitepoint.com/forums/showthread.php?629565-Abstract-ststants – Gordon

+1

Questo è meglio della risposta accettata. Se una classe astratta dipende dalla classe figlio, definire un metodo astratto per dichiarare questa dipendenza e utilizzare il metodo per ottenere il valore dalla classe di implementazione. – Kwebble

15
Purtroppo non

... una costante è esattamente quello che dice sulla latta, costante. Una volta definito, non può essere ridefinito, quindi in questo modo è impossibile richiedere la sua definizione tramite l'ereditarietà o le interfacce di PHP.

Tuttavia ... è possibile verificare se la costante è definita nel costruttore della classe genitore. In caso contrario, lancia un'eccezione.

abstract class A 
{ 
    public function __construct() 
    { 
     if (!defined('static::BLAH')) 
     { 
      throw new Exception('Constant BLAH is not defined on subclass ' . get_class($this)); 
     } 
    } 
} 

class B extends A 
{ 
    const BLAH = 'here'; 
} 

$b = new B(); 

Questo è il modo migliore che posso pensare di fare questo dalla descrizione iniziale.

+4

Il valore di una costante può essere sovrascritto in una classe figlia. Le costanti non sono immuni da quel tipo di ridefinizione. – Brilliand

11

Questo può essere un po 'un' hack ', ma esegue il lavoro con uno sforzo minimo, ma solo con un messaggio di errore diverso se la costante non è dichiarata nella classe figlio.

Una dichiarazione di costante auto-referenziale è sintatticamente corretto e analizza senza problemi, solo gettando un errore se tale dichiarazione è effettivamente eseguito in fase di esecuzione, in modo da una dichiarazione di auto-referenziale nella classe astratta must essere ignorato in una classe figlia altrimenti ci sarà un errore fatale: Cannot declare self-referencing constant.

In questo esempio, la classe genitore astratta obbliga tutti i propri figli a dichiarare la variabile NAME. Questo codice funziona correttamente, con l'emissione di Donald.Tuttavia, se la classe figlio Fooling ha non dichiarare la variabile, l'errore irreversibile verrebbe attivato.

<?php 

abstract class Foo { 

    // Self-referential 'abstract' declaration 
    const NAME = self::NAME; 

} 

class Fooling extends Foo { 

    // Overrides definition from parent class 
    // Without this declaration, an error will be triggered 
    const NAME = 'Donald'; 

} 

$fooling = new Fooling(); 

echo $fooling::NAME; 
+1

Grazie a @WebSmithery –

Problemi correlati