如何对“私有”构造函数进行例外处理?

时间:2019-05-18 14:00:46

标签: php oop friend

我想声明一个非公共构造函数,因此该类的用户不能直接调用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中映射此新实例,而不创建任何会破坏我的模型类“封装保护”的构造函数或设置方法?

1 个答案:

答案 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

相关问题