如何对 "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