PHP面向对象编程问题

3

在PHP 5.3中,是否有可能要求对象包含某些常量或属性?我读了一些关于PHP接口模型的内容,似乎它仅适用于抽象公共方法,所以这个方法不太行。因此,我的问题是:如果有两个对象Object A和Object B。如果Object B想要扩展Object A,它必须包含一个特定的常量或变量。你会如何设计这种架构?谢谢。


1
我从未说过它们不能有常量,我的观点仅是接口属性似乎只需要方法,常量似乎无法按预期工作。也许当我说“仅适用于”时应该更清楚。 - chrisw
4个回答

2

http://php.net/manual/zh/language.oop5.interfaces.php#language.oop5.interfaces.constants

接口可以拥有常量。接口常量的工作原理与类常量完全相同,只是不能被继承它的类/接口覆盖。

接口常量不能被继承类覆盖。类常量可以被覆盖,但不是必须的(即使在抽象类中声明)。抽象类旨在强制实现接口,而不是实现细节。常量属于实现细节,而方法则定义了接口。因此,虽然可以在抽象类中声明带有默认值的常量,但决定是否使用或重新定义它们取决于子类。

最佳方案是使用“getter”方法,例如:

abstract class MyAbstract
{
    abstract public function getPropertyA();
    abstract public function getPropertyB();
}

现在,任何使用extend MyAbstract的类都需要定义getPropertyA()getPropertyB(),这确保了这些值始终可访问。

1
戈登,如果你有对象A实现接口A,然后对象B扩展对象A,再让对象C扩展对象B,那么对象C将能够重新定义常量。不确定这是否是预期行为? - chrisw
@chrisw让我试试看。听起来像是个bug。你能在codepad上提供一个例子吗? - Gordon
@chrisw,关于这个问题在PHP中正在进行讨论。我认为目前的共识是这是“未记录的行为”,不应该依赖它(不确定它是否被视为“错误”或批准为“特性”)。 - Unsigned
@Gordon 这是一条关于 PHP 手册的评论,附带演示代码:http://www.php.net/manual/en/language.oop5.interfaces.php#102755 - Unsigned
@Unsigned Code labs:我怀疑这不会被认为是一个特性。常量应该是恒定的(还有什么?)。它们不应该被重新定义。 - netcoder
2
@netcoder:我完全同意你的观点,我认为这是一个bug。 - Unsigned

1

是和不是。

不是,因为属性是一种实现细节。它根本不是接口的一部分(方法定义了接口)。您可以在类中定义属性和常量(在类或接口中),但不能将它们标记为抽象并要求派生类“实现”它们。

是的,因为接口允许您定义所有派生类都将拥有的常量(请小心处理,请参见@Gordon的问题)。这会“强制”类具有这些常量。您还可以使用抽象类或常规继承“强制”将属性传递给派生类:

abstract class Foo {
   public $foo = 'bar';
   protected $bar = 'baz';
}

class Bar extends Foo {
   public funciton getBar() {
      return $this->bar;
   }
}

$bar = new Bar;
echo $bar->foo;      // bar
echo $bar->getBar(); // baz

0

对象A和对象B应该是类,对象是类的实例(我可能错了,但是...)。

有了这个想法,你可以让Class B扩展Class A,然后如果你想让Class B有一个特定的常量定义,Class A应该实现一个接口。阅读更多关于php接口的信息。


0

如果B对象扩展自A对象,并且A对象包含一个常量或变量,那么如果该变量是protectedpublic的,B对象也将包含它们。因此,即使变量的值为NULL,如果您在A对象中定义了变量,则B对象也将定义它。

您无法强制B对象实现未从A对象继承的常量。同样,如果B对象实现了包含常量的接口C,则它将继承这些常量。但是,B对象可以定义与其父类或接口不同的常量值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接