【问题标题】:Cannot implement two interfaces that have the same method name无法实现具有相同方法名称的两个接口
【发布时间】:2011-07-26 17:43:54
【问题描述】:

这不起作用:

interface TestInterface
{
    public function testMethod();
}

interface TestInterface2
{
    public function testMethod();
}

class TestClass implements TestInterface, TestInterface2
{

}

给我错误:

致命错误:无法继承抽象函数 TestInterface2::testMethod()(之前在 TestInterface 中声明了抽象)。

正确吗?为什么不允许这样做?对我来说没有意义。

抽象函数也会发生这种情况,例如,如果您实现了一个接口,然后从具有同名抽象函数的类继承。

【问题讨论】:

    标签: php oop interface


    【解决方案1】:

    实现两个包含具有相同签名的方法的接口是没有意义的。

    编译器无法知道这些方法是否真正具有相同的目的 - 如果不是,则意味着您的类不能至少实现一个接口。

    例子:

    interface IProgram { function execute($what); /* executes the given program */ }
    interface ISQLQuery { function execute($what); /* executes the given sql query */ }
    
    class PureAwesomeness implements IProgram, ISQLQuery {
        public function execute($what) { /* execute something.. but what?! */ }
    }
    

    如您所见,不可能为两个接口都实现该方法 - 也无法从给定接口调用实际实现该方法的方法。

    【讨论】:

    • 但是接口的全部意义在于它们没有实现。如果你想让你的类能够被传递给一个函数,该函数为参数指定一个接口,另一个指定另一个接口,但两者都有一个共同的方法?像“getName()”这样的方法名称在不同的接口上不会有不同的用途。
    • 在这种情况下,您应该创建一个新界面,例如INamed 只包含 getName() 方法。
    • 它们没有实现,但它们确实有语义,至少是隐含的。虽然您可以在接口中实现一个方法,以便在使用它的不同类中具有完全不同的含义,但这与接口的精神背道而驰。但是,如果您实现两个不同的接口,则无法保证它们的说明符相互了解,因此名称相似的方法具有相似的语义。我猜你可以让每个接口扩展一个包含通用方法的通用接口。
    • 在 Windows 上使用 PHP 5.3.10 实现具有相同签名的接口非常适合我。它不适用于我的 PHP 5.3.3 Linux 设置;在那里,我得到了与原始海报相同的错误。
    • 实现具有相同签名的接口可以有意义,甚至是possible since PHP-5.3.9
    【解决方案2】:

    这是不允许的,因为 PHP 不能确定哪个接口有你想要的方法。在您的情况下,它们是相同的,但想象一下它们是否具有不同的参数。

    您应该重新考虑您的应用程序设计。

    【讨论】:

      【解决方案3】:

      The PHP manual 明确表示:

      在 PHP 5.3.9 之前,一个类不能实现两个指定同名方法的接口,因为这会导致歧义。只要重复的方法具有相同的签名,最新版本的 PHP 就允许这样做。

      【讨论】:

      • 我不明白歧义可能在哪里,因为没有实现(这就是接口的重点)。我明白为什么你不想要具有不同签名的相同方法,但是,对于相同的签名,这不应该留给具体的实现来处理吗?例如,Java 不就是这样工作的吗?
      • 我认为你所说的有一个论据:这是语言设计者在多大程度上保护你免受自己伤害的决定。没有内在歧义,但如果接口具有具有相同签名的函数,则它们需要的函数语义可能匹配,或者它们可能完全不同。
      • 这似乎倒退了。难道不应该只允许他们有不同的签名吗?如果这两种方法具有不同的签名,那么任何调用其中一种方法的人都会显式调用他们想要的特定方法。即使这两种方法有两个完全不同的目标,也没关系,因为会调用正确的方法。但是,如果两个方法具有相同的签名并且每个方法的目标完全不同,那么就不可能有一个可以同时服务于这两个目的的方法,因此单个方法没有意义。谁能提供一些反驳理由?
      【解决方案4】:
      interface BaseInterface
      {
          public function testMethod();
      }
      
      interface TestInterface extends BaseInterface
      {
      }
      
      interface TestInterface2 extends BaseInterface
      {
      }
      
      class TestClass implements TestInterface, TestInterface2
      {
          public function testMethod()
          {
          }
      }
      

      【讨论】:

        【解决方案5】:

        看来当前的 PHP 版本实际上可以做到这一点。我已经跟踪到这次提交的行为变化:

        https://github.com/php/php-src/commit/31ef559712dae57046b6377f07634ad57f9d88cf#Zend/zend_compile.c

        因此,从 php-5.3.9 开始,记录在案的行为似乎发生了变化。

        【讨论】:

          猜你喜欢
          • 2015-10-19
          • 2015-03-11
          • 2022-01-22
          • 2018-11-04
          • 2017-01-19
          • 2011-12-13
          • 2011-11-23
          • 2013-07-03
          • 1970-01-01
          相关资源
          最近更新 更多