2011-09-06 21 views
10

Tôi cần tạo một lớp không thay đổi mà chỉ đơn giản là vùng chứa thành viên. Tôi muốn các trường của nó được khởi tạo một lần trong hàm tạo của nó (các giá trị sẽ được đưa ra như các tham số cho hàm tạo). Tôi muốn các lĩnh vực được công khai nhưng không thay đổi. Tôi có thể thực hiện nó với Java bằng cách sử dụng từ khóa final trước mỗi trường. Làm thế nào là nó được thực hiện trong PHP?PHP: các trường thành viên công khai không thể thay đổi

+3

này là không thể trong PHP. – Sjoerd

+0

Tại sao các trường phải được công khai? – Pete171

+0

@ pete171 có lẽ vì vậy chúng chỉ đọc – fbstj

Trả lời

16

Bạn nên sử dụng __set__get magic method và kê khai tài sản đó như protected hay private:

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 
    } 
} 

Cách sử dụng:

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

Output:

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

Bạn có thể sử dụng phương pháp ma thuật __set() và ném ngoại lệ khi ai đó cố gắng đặt thuộc tính trực tiếp.

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

Tuy nhiên, điều này sẽ ngăn việc sửa đổi thuộc tính bất kể chúng có công khai hay không.

+0

Cho rằng các thuộc tính nên được tuyên bố riêng/được bảo vệ, điều đó không thêm bất cứ điều gì hữu ích. '__get()' mặt khác, là những gì chúng ta muốn. – Mchl

+3

__set() được chạy khi ghi dữ liệu vào các thuộc tính không thể tiếp cận. Nó không hoạt động với công khai – jbrond

2

magic methods

để bạn có thể làm tốt hơn - nếu bạn có một số dinamyc ruộng

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' không được gọi cho các thuộc tính công khai – sanmai

Các vấn đề liên quan