PHP的抽象属性

有没有什么办法可以在PHP中定义抽象类属性?

abstract class Foo_Abstract { abstract public $tablename; } class Foo extends Foo_Abstract { //Foo must 'implement' $property public $tablename = 'users'; } 

没有定义财产这样的事情。

您只能声明属性,因为它们是初始化时在内存中保留的数据的容器。

另一方面,函数可以被声明(types,名称,参数)而不被定义(函数体缺失),因此可以被抽象化。

“摘要”只是表示声明了一些东西,但没有定义,所以在使用之前,需要定义它,否则就变成无用的。

不,没有办法用编译器强制执行,你必须使用$tablenamevariables的运行时检查(比如在构造函数中),例如:

 class Foo_Abstract { public final function __construct(/*whatever*/) { if(!isset($this->tablename)) throw new LogicException(get_class($this) . ' must have a $tablename'); } } 

为了对Foo_Abstract的所有派生类强制执行此操作,您必须将Foo_Abstract的构造函数作为final防止重写。

你可以声明一个抽象的getter:

 abstract class Foo_Abstract { abstract public function get_tablename(); } class Foo extends Foo_Abstract { protected $tablename = 'tablename'; public function get_tablename() { return $this->tablename; } } 

如上所述,没有这个确切的定义。 但是,我使用这个简单的解决方法来强制子类定义“抽象”属性:

 abstract class Father { public $name; abstract protected function setName(); // now every child class must declare this // function and thus declare the property public function __construct() { $this->setName(); } } class Son extends Father { protected function setName() { $this->name = "son"; } function __construct(){ parent::__construct(); } } 

根据属性的上下文,如果我想强制在子对象中声明一个抽象对象属性,我喜欢在抽象对象构造函数或setter / getter方法中使用static属性的static关键字。

除此之外,如果重新定义,子对象将覆盖父对象的属性和方法。 例如,如果某个属性在父级中被声明为protected ,并且在子级中被重新定义为public ,则最终的属性是公共的。 但是,如果该财产在父母中被宣布为private ,则该财产将保持private并且不可供儿童使用。

http://www.php.net//manual/en/language.oop5.static.php

 abstract class AbstractFoo { public $bar; public function __construct() { $this->bar = static::BAR; } } class Foo extends AbstractFoo { //const BAR = 'foobar'; } $foo = new Foo; //Fatal Error: Undefined class constant 'BAR' (uncomment const BAR = 'foobar';) echo $foo->bar; 

正如你可以通过testing你的代码发现的:

致命错误:无法在第3行中声明属性

不,那里没有。 不能在PHP中声明属性。

不过,你可以实现一个getter / setter函数的抽象,这可能是你在找什么。

属性没有实现(特别是公共属性),它们只是存在(或不):

 $foo = new Foo; $foo->publicProperty = 'Bar'; 

我今天也问过自己同样的问题,我想补充两分钱。

我们想要abstract属性的原因是为了确保子类定义它们,并在没有的时候抛出exception。 在我的具体情况下,我需要一些可以与static盟友合作的东西。

理想情况下,我想这样的事情:

 abstract class A { abstract protected static $prop; } class B extends A { protected static $prop = 'B prop'; // $prop defined, B loads successfully } class C extends A { // throws an exception when loading C for the first time because $prop // is not defined. } 

我结束了这个实现

 abstract class A { // no $prop definition in A! public static final function getProp() { return static::$prop; } } class B extends A { protected static $prop = 'B prop'; } class C extends A { } 

正如你所看到的,在A我没有定义$prop ,但是我在一个static getter中使用它。 因此,下面的代码工作

 B::getProp(); // => 'B prop' $b = new B(); $b->getProp(); // => 'B prop' 

另一方面,在C ,我没有定义$prop ,所以我得到exception:

 C::getProp(); // => Exception! $c = new C(); $c->getProp(); // => Exception! 

我必须调用getProp()方法来获取exception,我不能在类加载,但它是非常接近所需的行为,至less在我的情况。

我将getProp()定义为final以避免某个聪明的人 (也就是6个月以来)试图做的事情

 class D extends A { public static function getProp() { // really smart } } D::getProp(); // => no exception... 

如果tablename的值在对象的生命期内永远不会改变,那么下面将是一个简单而安全的实现。

 abstract class Foo_Abstract { abstract protected function getTablename(); public function showTableName() { echo 'my table name is '.$this->getTablename(); } } class Foo extends Foo_Abstract { //Foo must 'implement' getTablename() protected function getTablename() { return 'users'; } } 

这里的关键是string值'users'是在子类实现中的getTablename()中直接指定和返回的。 该函数模仿“只读”属性。

这与之前发布的使用附加variables的解决scheme非常相似。 我也喜欢Marco的解决scheme,虽然可能会更复杂一些。