7.4+:
Tin tốt là nó sẽ được triển khai trong các bản phát hành mới, như @Andrea đã chỉ ra. Tôi sẽ chỉ để lại giải pháp này ở đây trong trường hợp ai đó muốn sử dụng nó trước 7.4
7,3 trở xuống
Dựa trên các thông báo tôi vẫn nhận được từ chủ đề này, tôi tin rằng nhiều người ngoài kia đã / đang gặp phải vấn đề tương tự như tôi. Giải pháp của tôi cho trường hợp này là kết hợp setters + __set
magic method bên trong một đặc điểm để mô phỏng hành vi này. Nó đây:
trait SettersTrait
{
public function __set($name, $value)
{
$setter = 'set'.$name;
if (method_exists($this, $setter)) {
$this->$setter($value);
} else {
$this->$name = $value;
}
}
}
Và đây là minh chứng:
class Bar {}
class NotBar {}
class Foo
{
use SettersTrait;
private $bar;
protected function setBar(Bar $bar)
{
$this->bar = $bar;
}
}
$foo = new Foo();
$foo->bar = new NotBar();
Giải trình
Trước hết, hãy định nghĩa bar
là một thuộc tính riêng để PHP sẽ truyền __set
tự động .
__set
sẽ kiểm tra nếu có một số setter được khai báo trong đối tượng hiện tại ( method_exists($this, $setter)
). Nếu không, nó sẽ chỉ đặt giá trị của nó như bình thường.
Khai báo phương thức setter (setBar) nhận đối số gợi ý kiểu ( setBar(Bar $bar)
).
Miễn là PHP phát hiện ra rằng một cái gì đó không phải là Bar
phiên bản đang được chuyển đến setter, nó sẽ tự động kích hoạt Lỗi nghiêm trọng: Uncaught TypeError: Đối số 1 được chuyển tới Foo :: setBar () phải là một phiên bản của Bar, phiên bản NotBar đã cho