php PHP抽象属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7634970/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP abstract properties
提问by Tamás Pap
Is there any way to define abstract class properties in PHP?
有没有办法在 PHP 中定义抽象类属性?
abstract class Foo_Abstract {
abstract public $tablename;
}
class Foo extends Foo_Abstract {
//Foo must 'implement' $property
public $tablename = 'users';
}
回答by Mathieu Dumoulin
There is no such thing as defining a property.
没有定义属性这样的东西。
You can only declare properties because they are containers of data reserved in memory on initialization.
您只能声明属性,因为它们是初始化时保留在内存中的数据容器。
A function on the other hand can be declared (types, name, parameters) without being defined (function body missing) and thus, can be made abstract.
另一方面,函数可以被声明(类型、名称、参数)而不被定义(函数体缺失),因此可以被抽象化。
"Abstract" only indicates that something was declared but not defined and therefore before using it, you need to define it or it becomes useless.
“抽象”仅表示已声明但未定义的内容,因此在使用它之前,您需要定义它,否则它将变得无用。
回答by connec
No, there is no way to enforce that with the compiler, you'd have to use run-time checks (say, in the constructor) for the $tablenamevariable, e.g.:
不,编译器无法强制执行此操作,您必须对$tablename变量使用运行时检查(例如,在构造函数中),例如:
class Foo_Abstract {
public final function __construct(/*whatever*/) {
if(!isset($this->tablename))
throw new LogicException(get_class($this) . ' must have a $tablename');
}
}
To enforce this for all derived classes of Foo_Abstract you would have to make Foo_Abstract's constructor final, preventing overriding.
要对 Foo_Abstract 的所有派生类强制执行此操作,您必须创建 Foo_Abstract 的构造函数final,以防止覆盖。
You could declare an abstract getter instead:
您可以改为声明一个抽象的 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;
}
}
回答by fyrye
Depending on the context of the property if I want to force declaration of an abstract object property in a child object, I like to use a constant with the statickeyword for the property in the abstract object constructor or setter/getter methods. You can optionally use finalto prevent the method from being overridden in extended classes.
根据属性的上下文,如果我想在子对象中强制声明抽象对象属性,我喜欢static在抽象对象构造函数或 setter/getter 方法中使用带有关键字的常量。您可以选择使用final来防止该方法在扩展类中被覆盖。
Other than that the child object overrides the parent object property and methods if redefined.
For example if a property is declared as protectedin the parent and redefined as publicin the child, the resulting property is public. However if the property is declared privatein the parent it will remain privateand not available to the child.
除此之外,如果重新定义,子对象将覆盖父对象属性和方法。例如,如果一个属性protected在父级中声明并在子级中重新定义public,则结果属性是公共的。但是,如果该属性private在父级中声明,它将保留private并且对子级不可用。
http://www.php.net//manual/en/language.oop5.static.php
http://www.php.net//manual/en/language.oop5.static.php
abstract class AbstractFoo
{
public $bar;
final 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;
回答by ulkas
As stated above, there is no such exact definition. I, however, use this simple workaround to force the child class to define the "abstract" property:
如上所述,没有这样确切的定义。但是,我使用这个简单的解决方法来强制子类定义“抽象”属性:
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();
}
}
回答by hakre
As you could have found out by just testing your code:
正如您可以通过测试您的代码发现的那样:
Fatal error: Properties cannot be declared abstract in ... on line 3
致命错误:属性不能在第 3 行中声明为抽象...
No, there is not. Properties cannot be declared abstract in PHP.
不,那里没有。属性不能在 PHP 中声明为抽象的。
However you can implement a getter/setter function abstract, this might be what you're looking for.
但是,您可以实现一个 getter/setter 函数抽象,这可能是您正在寻找的。
Properties aren't implemented (especially public properties), they just exist (or not):
未实现属性(尤其是公共属性),它们只是存在(或不存在):
$foo = new Foo;
$foo->publicProperty = 'Bar';
回答by Marco Pallante
I've asked myself the same question today, and I'd like to add my two cents.
我今天问了自己同样的问题,我想加上我的两分钱。
The reason we would like abstractproperties is to make sure that subclasses define them and throw exceptions when they don't. In my specific case, I needed something that could work with statically.
我们想要abstract属性的原因是确保子类定义它们并在它们不定义时抛出异常。在我的具体情况下,我需要一些可以与static盟友一起工作的东西。
Ideally I would like something like this:
理想情况下,我想要这样的东西:
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.
}
I ended up with this implementation
我结束了这个实现
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
{
}
As you can see, in AI don't define $prop, but I use it in a staticgetter. Therefore, the following code works
如您所见,在AI 中没有定义$prop,但我在static吸气剂中使用它。因此,以下代码有效
B::getProp();
// => 'B prop'
$b = new B();
$b->getProp();
// => 'B prop'
In C, on the other hand, I don't define $prop, so I get exceptions:
在C,在另一方面,我并不确定$prop,所以我得到的例外:
C::getProp();
// => Exception!
$c = new C();
$c->getProp();
// => Exception!
I must call the getProp()?method to get the exception and I can't get it on class loading, but it is quite close to the desired behavior, at least in my case.
我必须调用getProp()?method 来获取异常,我无法在类加载时获取它,但它非常接近所需的行为,至少在我的情况下是这样。
I define getProp()as finalto avoid that some smart guy(aka myself in 6 months) is tempted to do
我定义getProp()为final避免一些聪明人(也就是 6 个月后的我)被诱惑去做
class D extends A {
public static function getProp() {
// really smart
}
}
D::getProp();
// => no exception...
回答by sevavietl
The need for abstract properties can indicate design problems. While many of answers implement kind of Template method patternand it works, it always looks kind of strange.
对抽象属性的需求可以表明设计问题。虽然许多答案实现了一种模板方法模式并且它有效,但它看起来总是有点奇怪。
Let's take a look at the original example:
让我们看一下原始示例:
abstract class Foo_Abstract {
abstract public $tablename;
}
class Foo extends Foo_Abstract {
//Foo must 'implement' $property
public $tablename = 'users';
}
To mark something abstractis to indicate it a must-have thing. Well, a must-have value(in this case) is a required dependency, so it should be passed to the constructor during instantiation:
标记某物abstract就是表明它是必备的东西。好吧,必须要有值(在这种情况下)是必需的依赖项,因此应该在实例化期间将其传递给构造函数:
class Table
{
private $name;
public function __construct(string $name)
{
$this->name = $name;
}
public function name(): string
{
return $this->name;
}
}
Then if you actually want a more concrete named class you can inherit like so:
然后,如果你真的想要一个更具体的命名类,你可以像这样继承:
final class UsersTable extends Table
{
public function __construct()
{
parent::__construct('users');
}
}
This can be useful if you use DI container and have to pass different tables for different objects.
如果您使用 DI 容器并且必须为不同的对象传递不同的表,这会很有用。
回答by Dropa
PHP 7 makes it quite a bit easier for making abstract "properties". Just as above, you will make them by creating abstract functions, but with PHP 7 you can define the return type for that function, which makes things a lot easier when you're building a base class that anyone can extend.
PHP 7 使创建抽象“属性”变得更加容易。就像上面一样,您将通过创建抽象函数来创建它们,但是在 PHP 7 中,您可以定义该函数的返回类型,这在构建任何人都可以扩展的基类时变得容易多了。
<?php
abstract class FooBase {
abstract public function FooProp(): string;
abstract public function BarProp(): BarClass;
public function foo() {
return $this->FooProp();
}
public function bar() {
return $this->BarProp()->name();
}
}
class BarClass {
public function name() {
return 'Bar!';
}
}
class FooClass extends FooBase {
public function FooProp(): string {
return 'Foo!';
}
public function BarProp(): BarClass {
// This would not work:
// return 'not working';
// But this will!
return new BarClass();
}
}
$test = new FooClass();
echo $test->foo() . PHP_EOL;
echo $test->bar() . PHP_EOL;
回答by ck.tan
if tablename value will never change during the object's lifetime, following will be a simple yet safe implementation.
如果 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';
}
}
the key here is that the string value 'users' is specified and returned directly in getTablename() in child class implementation. The function mimics a "readonly" property.
这里的关键是在子类实现中的 getTablename() 中指定并直接返回字符串值 'users'。该函数模仿“只读”属性。
This is fairly similar to a solution posted earlier on which uses an additional variable. I also like Marco's solution though it can be a bit more complicated.
这与之前发布的使用附加变量的解决方案非常相似。我也喜欢 Marco 的解决方案,尽管它可能有点复杂。

