2011-09-06 16 views
10

Necesito crear una clase inmutable que sea simplemente un contenedor de campo miembro. Quiero que sus campos sean instanciados una vez en su constructor (los valores deben darse como parámetros para el constructor). Quiero que los campos sean públicos pero inmutables. Pude haberlo hecho con Java usando la palabra clave final antes de cada campo. ¿Cómo se hace en PHP?PHP: campos de miembros públicos inmutables

+3

Esto no es posible en PHP. – Sjoerd

+0

¿Por qué los campos deben ser públicos? – Pete171

+0

@ pete171 probablemente sean solo de lectura – fbstj

Respuesta

16

Debe utilizar __set y __get métodos mágicos y declarar que la propiedad protegido o privado:

class Example 
{ 
    private $value; 

    public function __construct() 
    { 
     $this->value = "test"; 
    } 

    public function __get($key) 
    { 
     if (property_exists($this, $key)) { 
      return $this->{$key}; 
     } else { 
      return null; // or throw an exception 
     } 
    } 

    public function __set($key, $value) 
    { 
     return; // or throw an exception 
    } 
} 

Uso:

$example = new Example(); 
var_dump($example->value); 
$example->value = "invalid"; 
var_dump($example->value); 

Salida:

string(4) "test" 
string(4) "test" 
2

Puede usar el método mágico __set() y lanzar una excepción cuando alguien intenta establecer una propiedad directamente.

class ClassName { 
    public function __set($key, $value) { 
     throw new Exception('Can't modify property directly.'); 
    } 
} 

Sin embargo, esto evitaría la modificación de las propiedades independientemente de si son públicas o no.

+0

Dado que las propiedades deben declararse privadas/protegido de todos modos, eso no agrega nada útil. '__get()' por otro lado, es lo que queremos. – Mchl

+3

__set() se ejecuta al escribir datos en propiedades inaccesibles. No funciona con public – jbrond

2

magic methods

por lo que se puede hacer mejor - si tiene un recuento Dinamyc de campos

class ClassName { 
     private $fields = array(); 
     // use class : $cl = new ClassName(array('f'=>2,'field_4'=>5,''12)); 
     // echo $cl->field_4; echo $cl->f; 
     public function __construct($data= array()) 
     { 
      if (!is_array($data) || !count($data)) throw new Exception('Not enough args') 
      foreach ($data as $key=>$val) 
      { 
       if (is_numeric($key)) 
       $this->fields['field_'.$key] = $val; 
       else 
       $this->fields[$key] = $val; 
      }  
     } 
      /* in this case you can use this class like $cl = new ClassName(12,14,13,15,12); echo $cl->field_1; 
     public function __construct() 
    { 
      $ata = funcs_get_args(); 

      if (!count($data)) throw new Exception('Not enough args') 
      foreach ($data as $key=>$val) 
      { 
       if (is_numeric($key)) 
       $this->fields['field_'.$key] = $val; 
       else 
       $this->fields[$key] = $val; 
      }  
    } 
    */ 
     public function __get($var) { 
      if (isset($this->fields[$var])) 
       return $this->fields[$var]; 
      return false; 
      //or throw new Exception ('Undeclared property'); 
     } 
    } 
+4

'__set' no recibe llamadas para propiedades públicas – sanmai

Cuestiones relacionadas