我想声明一个非公共构造函数,因此该类的用户不能直接调用new Message()
,而必须从在Message
的抽象类上声明的静态生成器方法实例化该对象。扩展。
到目前为止,我的代码是:
abstract class SqlDecodable {
public function instanceFromRawSql (array $rawSql) {
$newInstanceToReturn = new static() // problem is here
// .. map the new instance ..
return $newInstance ;
}
}
// for exemple...
class Message extends SqlDecodable {
private $receiverId ;
private $senderId ;
private $text ;
private/protected/public?? function __construct() {
// problem here : this constructor should be usable only by
parent class, not for user of Message
}
static function propertiesToSqlFields() {
return [
"receiverId" => "receiver_id_field_in_db",
"senderId" => "sender_id",
"text" => "text"
]
}
}
这实际上更复杂,但是我简化了此问题的系统
实现方法instanceFromRawSqlArray
时,必须创建子类$instanceToReturn = new static()
的新实例,然后逐个设置变量。
但是,我不想让__construct在我的模型类中不包含任何参数。我不希望Message的开发用户能够new Message()
。
该构造函数只能由instanceFromRawSqlArray
使用。
问题是,正如我所看到的,PHP中没有C ++老友记类。我不能使我的__construct受保护,因为如我所见,受保护的方法可用于子级而不是父级。
您是否有想法在方法instanceFromRawSqlArray中映射此新实例,而不创建任何会破坏我的模型类“封装保护”的构造函数或设置方法?
答案 0 :(得分:2)
您非常亲密。您可以简单地将构造函数声明为protected
。
直接实例化该类是行不通的,但是您可以从抽象类中声明的静态方法中调用new
。
例如:
abstract class SuperAbstract {
static function create() {
return new static();
}
}
class Extended extends SuperAbstract {
private $hello = '';
protected function __construct() {
$this->hello = "world";
}
public function hello() {
return "hello " . $this->hello;
}
}
// works
$a = Extended::create();
echo $a->hello(); // outputs "hello world"
// can't touch this. This will fail because the constructor is `protected`.
$b = new Extended();
当然,由于它是protected
,所以构造函数也可以从子类中调用。这是不可避免的,只要孩子上课是可能的。但是您也可以将Extended
声明为final
,从而无法扩展该类。因此,只能从抽象父级中定义的工厂方法创建新实例。
final Extended extends SuperAbstract
protected function __construct() { }
}
您可以在此处查看它的运行情况(失败):https://3v4l.org/LliKj