我有一组扩展抽象类的类。抽象类包含使用后期静态绑定来获取子类中定义的信息的方法。例如,抽象类可能有一个包含行的方法:
$var = static::$childVar . ' some text';
通过这种方式,可以在运行时为抽象类中定义的方法生成基于子类中定义的变量值的不同字符串。
我想要做的是有一些强制子类声明这个变量的机制,如果没有设置变量,则消除了调用该方法的可能性。
使用接口,可能需要一个类来定义方法(和常量,遗憾的是,它们不能使用public / protected / private修改其可见性)。因此,如果类实现了接口,但未定义接口中指定的所有方法,则会生成错误。但是,没有办法使用接口来要求类定义属性。
我已经看到一些建议在接口中使用getter方法(例如getChildVar())隐式需要变量声明的材料,但这不适合我,因为我不希望变量可以在类外访问(他们有protected
种可见度。
同样,常量不起作用,因为它们不支持protected
可见性修饰符。
我知道我总是可以使用isset()
语句在抽象类的方法(甚至是构造函数)中检查这一点,但与使用接口确保方法定义相比,这似乎是不优雅的。我想知道是否有一些标准的方法可以在我的抽象类中硬编码需求。
顺便说一句,如果有人知道为什么你不能在接口内声明变量,我有兴趣知道原因是什么。这对我来说似乎是一个重大的疏忽。
非常感谢任何帮助。
答案 0 :(得分:13)
您无法在界面中强制执行变量,因为界面是如何使用您的类的公共表示。如果我是另一个开发项目的开发人员,我希望能够查看该接口,并且知道我可以假设的所有方法都在类中实现,并且实现该接口。这并非与私人或受保护财产有关,或与此有关的任何特定财产。 Getter / setter是这类事情的标准。
现在的疏忽是,您无法使用魔法来尝试访问未定义的静态属性。这对你来说是理想的解决方案。
如果在运行时声明静态属性,为什么不强制执行setChildVar()
方法,或者放置一个获取后期静态绑定属性的父类方法,如果未设置则抛出错误?您甚至可以实现“驱动程序”模式来实现此目的:
<?php
class MyParentClass {
public function __get($key)
{
if ( !isset(static::$$key))
{
throw new Exception('Child class '.get_called_class().' failed to define static '.$key.' property');
}
return static::$$key;
}
public function getText()
{
return $this->childVar . ' some text';
}
}
class MyChildClass extends MyParentClass {
protected static $childVar = 'some value:';
}
$a = new MyChildClass;
echo $a->getText(); // some value: some text