如何对 "private" 构造函数进行异常处理?
How to make an exception to "private" constructors?
我想声明一个 non-public 构造函数,这样 class 的用户就不能直接调用 new Message()
而必须从静态构建器实例化 object在 Message
扩展的抽象 class 上声明的方法。
到目前为止我的代码是:
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
时,我必须创建 child class 的新实例:$instanceToReturn = new static()
,然后一一设置变量.
尽管如此,我不想让 __construct 在我的模型中没有参数 classes。我不希望 Message 的开发用户能够 new Message()
。
此构造函数应该只能由 instanceFromRawSqlArray
使用。
问题是,正如我所见,PHP 中没有 C++ 朋友 class。我不能让我的 __construct 受保护,因为正如我所见,受保护的方法可用于 child,而不是 parent。
您是否有想法在方法 instanceFromRawSqlArray 中映射这个新实例,而不创建任何构造函数或 setter 会破坏我的模型 class "encapsulation protections"?
你们非常亲密。您可以简单地将构造函数声明为 protected
。
直接实例化 class 是行不通的,但您可以从抽象 class.
中声明的静态方法调用 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
,构造函数也可以从 children classes 调用。这是不可避免的,只要 children class 是可能的。但是您也可以将 Extended
声明为 final
,从而使 class 的扩展成为不可能。因此,只能从抽象 parent.
中定义的工厂方法创建新实例
final Extended extends SuperAbstract
protected function __construct() { }
}
您可以在此处看到它正在运行(和失败):https://3v4l.org/LliKj
我想声明一个 non-public 构造函数,这样 class 的用户就不能直接调用 new Message()
而必须从静态构建器实例化 object在 Message
扩展的抽象 class 上声明的方法。
到目前为止我的代码是:
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
时,我必须创建 child class 的新实例:$instanceToReturn = new static()
,然后一一设置变量.
尽管如此,我不想让 __construct 在我的模型中没有参数 classes。我不希望 Message 的开发用户能够 new Message()
。
此构造函数应该只能由 instanceFromRawSqlArray
使用。
问题是,正如我所见,PHP 中没有 C++ 朋友 class。我不能让我的 __construct 受保护,因为正如我所见,受保护的方法可用于 child,而不是 parent。
您是否有想法在方法 instanceFromRawSqlArray 中映射这个新实例,而不创建任何构造函数或 setter 会破坏我的模型 class "encapsulation protections"?
你们非常亲密。您可以简单地将构造函数声明为 protected
。
直接实例化 class 是行不通的,但您可以从抽象 class.
中声明的静态方法调用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
,构造函数也可以从 children classes 调用。这是不可避免的,只要 children class 是可能的。但是您也可以将 Extended
声明为 final
,从而使 class 的扩展成为不可能。因此,只能从抽象 parent.
final Extended extends SuperAbstract
protected function __construct() { }
}
您可以在此处看到它正在运行(和失败):https://3v4l.org/LliKj