Come implementare una sola lettura variabile membro in PHP?
-
23-09-2019 - |
Domanda
Quando si cerca di cambiarlo, un'eccezione.
Soluzione
Credo che una soluzione, per le proprietà di classe, sarebbe quello di:
- non definisce una proprietà con il nome che ti interessa
- utilizzare il metodo
__get
magica per accedere a tale proprietà, utilizzando il nome "falso" - definire il metodo
__set
modo viene generata un'eccezione quando si cerca di impostare la proprietà. - sovraccarico , per avere maggiori informazioni sui metodi di magia.
Per le variabili, non credo sia possibile avere una variabile di sola lettura per i quali il PHP un'eccezione quando si sta cercando di scrivere su di esso.
Per esempio, si consideri questa piccola classe:
class MyClass {
protected $_data = array(
'myVar' => 'test'
);
public function __get($name) {
if (isset($this->_data[$name])) {
return $this->_data[$name];
} else {
// non-existant property
// => up to you to decide what to do
}
}
public function __set($name, $value) {
if ($name === 'myVar') {
throw new Exception("not allowed : $name");
} else {
// => up to you to decide what to do
}
}
}
instanciating la classe e cercando di leggere la proprietà:
$a = new MyClass();
echo $a->myVar . '<br />';
ti porterà i risultati attesi:
test
Durante il tentativo di scrivere alla proprietà:
$a->myVar = 10;
si arriva un'eccezione:
Exception: not allowed : myVar in /.../temp.php on line 19
Altri suggerimenti
class test {
const CANT_CHANGE_ME = 1;
}
e si fa riferimento come test::CANT_CHANGE_ME
Con una costante. Chiave const
So che questa è una vecchia questione, ma la risposta di Pascal mi ha veramente aiutato e volevo aggiungere ad essa un po '.
__ get () spara non solo sulle proprietà inesistenti, ma "inaccessibili" quelli pure, ad esempio, quelle protette. In questo modo è facile fare proprietà di sola lettura!
class MyClass {
protected $this;
protected $that;
protected $theOther;
public function __get( $name ) {
if ( isset( $this->$name ) ) {
return $this->$name;
} else {
throw new Exception( "Call to nonexistent '$name' property of MyClass class" );
return false;
}
}
public function __set( $name ) {
if ( isset( $this->$name ) ) {
throw new Exception( "Tried to set nonexistent '$name' property of MyClass class" );
return false;
} else {
throw new Exception( "Tried to set read-only '$name' property of MyClass class" );
return false;
}
}
}
La risposta breve è che non è possibile creare una variabile membro oggetto di sola lettura in PHP.
In realtà, la maggior parte dei linguaggi orientati agli oggetti considerano cattiva forma per esporre le variabili membro comunque pubblicamente ... (C # è il grande, brutta eccezione con le sue proprietà costrutti).
Se si desidera una variabile di classe, utilizzare la parola chiave const
:
class MyClass {
public const myVariable = 'x';
}
Questa variabile si può accedere:
echo MyClass::myVariable;
Questa variabile esisterà esattamente una versione indipendentemente dal numero di oggetti diversi di tipo MyClass
creati, e in maggior parte degli scenari orientati agli oggetti ha poco o nessun uso.
Se, invece, si desidera una lettura unica variabile che può avere valori diversi per ogni oggetto, è necessario utilizzare una variabile privata membro e di un metodo di accesso (un k un getter):
class MyClass {
private $myVariable;
public function getMyVariable() {
return $this->myVariable;
}
public function __construct($myVar) {
$this->myVariable = $myVar;
}
}
La variabile è impostato nel costruttore, ed è stato fatto in sola lettura da non avere un regolatore. Ma ogni istanza di MyClass
può avere il proprio valore per i myVariable
.
$a = new MyClass(1);
$b = new MyClass(2);
echo $a->getMyVariable(); // 1
echo $b->getMyVariable(); // 2
$a->setMyVariable(3); // causes an error - the method doesn't exist
$a->myVariable = 3; // also error - the variable is private