2013-08-08 28 views
5

Bất cứ ai có thể vui lòng giải thích cho tôi một logic trong hành vi này?Quirky __set() ma thuật chức năng

Hãy xem xét các tình huống sau đây:

class EPPDomain 
{ 
    protected $myField; 

    public static function buildEPPDomain($fieldValue) 
    { 
     $me = new self(); 
     $me->myField = $fieldValue; 
     return $me; 
    } 

    public function __set($name, $value) 
    { 
     $this->$name = "prefix_".value; 
    } 
} 

class EPPDomainFactory 
{ 
    public static function buildEPPDomain($fieldValue) 
    { 
     $me = new EPPDomain(); 
     $me->myField = $fieldValue; 
     return $me; 
    } 
} 

Vì vậy

$dmn = EPPDomain::buildEPPDomain("myValue"); 
echo $dmn->myField; 

Dự kiến ​​

prefix_myValue 

thực tế

myValue 

Rõ ràng,

$dmn = EPPDomainFactory::buildEPPDomain("myValue"); 
echo $dmn->myField; 

trình như mong đợi xuất ra

prefix_myValue 

Theo __set mô tả trên http://www.php.net/manual/en/language.oop5.overloading.php#object.set

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

Khi tôi tạo một thể hiện EPPDomain trong phương pháp tĩnh của lớp EPPDomain, tất cả các thuộc tính được bảo vệ đều không thể truy cập được. Do đó __set nên được gọi nhưng nó không

là tôi biết nó cũng nói

tài sản quá tải chỉ hoạt động trong bối cảnh đối tượng. Những phương pháp ma thuật sẽ không được kích hoạt trong ngữ cảnh tĩnh. Do đó, các phương thức này không được khai báo tĩnh. Kể từ PHP 5.3.0, một cảnh báo được đưa ra nếu một trong các phương thức nạp chồng phép thuật được khai báo là tĩnh.

Nhưng tôi có một sự nhấn mạnh rằng nó chỉ ra rằng phương thức __set phải là một hàm thành viên của lớp và không được tĩnh. Đó là nó và có vẻ như nó không có gì để làm với tình hình tôi đang phải đối mặt.

Đó có phải là lỗi hoặc hành vi dự kiến ​​không?

+1

Sẽ rất có ích nếu bạn có thể * đơn giản hóa * mã mẫu đó. Nó quá phức tạp để chứng minh quan điểm của bạn. – deceze

+0

Xong, xin lỗi, mã của tôi phức tạp hơn nhiều và tôi đang cố đơn giản hóa nó càng nhiều càng tốt. Có lẽ đã không cố gắng hết sức. Phiên bản này sẽ trông đẹp hơn –

Trả lời

5

Một tài sản protectedtruy cập để tất cả các mã trong cùng một hoặc kế thừa lớp. Sự nhấn mạnh là trên lớp.

class Foo { 

    protected $bar; 

    public function foo() { 
     $foo = new self; 
     $foo->bar = 'baz'; 
    } 

} 

Điều này chỉ hoạt động tốt. Lớp đang hoạt động trên một bản sao của riêng mình là, nó có quyền truy cập vào các thuộc tính của riêng nó. Nó không phải là về "trường hợp nước ngoài", đó là về lớp học.

Điểm của thuộc tính được bảo vệ là sự hiện diện hoặc triển khai của chúng chỉ nên liên quan đến lớp xác định chúng.Mã khác không nên gây rối trực tiếp với họ. Vì người ta có thể giả định rằng một lớp biết cách xử lý các thuộc tính riêng của nó, một lớp được tin cậy để thao tác các thuộc tính của bất kỳ đối tượng nào thuộc loại của nó.

+1

Tốt, tôi không biết rằng các thuộc tính riêng tư/được bảo vệ sẽ vẫn có thể truy cập được ngay cả khi đối tượng được tạo trong phương thức nhà máy tĩnh thuộc cùng một lớp. Hiệu quả điều này buộc các nhà phát triển phải có phương pháp nhà máy trong các lớp khác nhau. Cám ơn bạn vì đã chỉ ra điều này –

0

Đó là hành vi mong đợi, bởi vì một phương pháp không có quyền truy cập vào các thuộc tính được bảo vệ (và thậm chí riêng tư) của các phiên bản của lớp của nó.

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