2011-10-17 19 views
6

Sto lavorando a un progetto in cui mi piacerebbe poter dichiarare una variabile membro statica all'interno di una classe base astratta. Ho una classe del modello, una classe intermedia postale, e, infine, una classe post site-specific, qualcosa di simile al seguente:Variabili statiche PHP in classi astratte

abstract class Model { 
    protected static $_table = null; 
    protected static $_database = null; 

    ... 
} 

abstract class PostModel extends Model { 
    public function __construct() { 
     if (!isset(self::$_table)) { 
      self::$_table = 'some_table'; 
     } 

     parent::__construct(); 
    } 

    ... 
} 

class SitePostModel extends PostModel { 
    public function __construct() { 
     if (!isset(self::$_database)) { 
      self::$_database = 'some_database'; 
     } 

     parent::__construct(); 
    } 

    ... 
} 

mi piacerebbe rendere evidente dalla classe del modello che il $ _Table e $ _database membri sono richiesti. Tuttavia, $ _table è davvero statico dal punto di vista della classe PostModel e $ _database è davvero statico dal punto di vista della classe SitePostModel.

È un modo legittimo per raggiungere il mio obiettivo? Dichiarare le variabili statiche nel Modello stesso implica che dovrebbero esistere solo una volta per la classe base astratta o solo una volta per la classe istanziata effettiva?

+4

* (riferimento) * [capitolo sulla parola chiave 'static'] (http://php.net/manual/en/language.oop5.static.php) e [capitolo su Late Static Binding] (http : //php.net/manual/en/language.oop5.late-static-bindings.php). – Gordon

+2

Per quanto riguarda se questo è legittimo o implica qualcosa, direi che questo è oggetto di discussione. IMO, non dovresti usare l'ereditarietà qui. Inoltre, Model solitamente non implica database. – Gordon

+0

Ho apprezzato l'input @Gordon. Penso che "il modello non implichi il database" sia sufficiente per convincermi a non trattare i membri in questo modo. Nell'immediato futuro, questa classe Model modellerà solo le tabelle del database, ma potrebbe non essere sempre così. – michaelxor

risposta

1

È un modo legittimo per raggiungere il mio obiettivo?

No. Non funziona, in modo che non supera un test di base per la legittimità.

Dichiarare le variabili statiche nel Modello stesso implica che dovrebbero esistere solo una volta per la classe base astratta o solo una volta per la classe istanziata effettiva?

Le variabili statiche sono globali, esistono una volta. Nel tuo caso per ogni nome di classe. Se hai tre nomi di classe, avresti tre variabili (globali). La parola chiave protetta controlla solo la visibilità/portata delle tre variabili statiche:

<?php 

class A { 
    protected static $v = 'red'; 
    public static function get() { return self::$v . ' - ' . static::$v;} 
} 

class B extends A { 
    protected static $v = 'blue'; 
} 

class C extends B { 
    protected static $v = 'green'; 
} 

echo C::get(); # red - green 
+0

Ci scusiamo per la (incredibilmente) risposta tardiva, ma vorrei solo chiarire. Hai detto che la mia soluzione non avrebbe funzionato. In effetti ho preso il consiglio di @ Gordon dall'alto, e ho spostato le variabili $ _table e $ _database dalla classe Model generica; tuttavia, se avessi lasciato il codice come mostrato sopra, potrei ancora usare statico :: $ _ database e static :: $ _ tabella nelle funzioni save()/load() per il modello e ottenere 'some_table' e 'some_database,' come mostra il tuo esempio. SitePostModel :: save() funzionerebbe davvero correttamente e sarebbe univoco da SomeOtherSitePostModel :: save(), no? – michaelxor

+0

"È un modo legittimo per raggiungere il mio obiettivo? No. Non funziona, quindi fallisce un test di base per la legittimità." -> Brillante;) – Mirko

0

recente ho incontrato lo stesso problema e sono giunti alla stessa soluzione - mettendo impostazioni in variabili statiche e l'accesso utilizzando la parola chiave static. Funziona anche nei casi in cui hai impostazioni predefinite (come il numero di righe per pagina) che potresti voler sovrascrivere in sottoclassi. Questo mi è sembrato il modo più intuitivo ed efficiente.

Alternative ho considerato:

  • utilizzare una funzione getter astratto statica. Richiede più linee di codice e più chiamate di funzione.
  • Mantenere le impostazioni in una variabile membro non statica e lasciare che il costruttore della classe figlio si preoccupi di ciò. Ho rifiutato questa opzione perché le classi di mio figlio non avevano altrimenti bisogno di un costruttore.