【问题标题】:Is it possible to have an interface that has private / protected methods?是否可以有一个具有私有/受保护方法的接口?
【发布时间】:2010-12-24 23:50:39
【问题描述】:

在 PHP 5 中是否有可能拥有一个具有私有/受保护方法的接口?

现在我有:

interface iService
{
    private method1();
}

这会引发错误:

解析错误:语法错误,意外的 T_STRING,期待 T_VARIABLE

我只想确认接口只能包含公共方法。

【问题讨论】:

  • 我发现答案令人失望。我也想要支持受保护/私有方法的接口。例如,我有一个类,其中抽象实现的公共方法依赖于子类实现的受保护方法。我想使用一个接口来要求子类实现抽象公共方法所需的受保护方法。
  • 为此目的使用抽象基类。您可以将这两种方法结合起来:接口中的公共方法,在定义(并依赖于)抽象受保护方法的抽象基类中实现这些方法。
  • 如果您可以声明私有或受保护方法,则应为private function method1 (); 而不是private method1();

标签: php oop interface


【解决方案1】:

如上所述,接口只能定义公开可见的方法。我想展示一个如何处理受保护方法的示例。要强制使用特定的受保护方法,可以创建一个实现接口的抽象类。

如果抽象类已经可以处理一些工作负载,以简化实际实现,这尤其有意义。例如,在这里,一个抽象类负责实例化结果对象,这总是需要的:

首先是界面。

interface iService
{
   /**
    * The method expects an instance of ServiceResult to be returned.
    * @return ServiceResult
    */
    public function doSomething();
}

然后抽象类定义内部方法结构:

abstract class AbstractService implements iService
{
    public function doSomething()
    {
        // prepare the result instance, so extending classes
        // do not have to do it manually themselves.
        $result = new ServiceResult();

        $this->process($result);

        return $result;
    }

   /**
    * Force all classes that extend this to implement
    * this method.
    *
    * @param ServiceResult $result
    */
    abstract protected function process($result);
}

实际实现的类自动继承抽象类的接口,只需要实现受保护的方法。

class ExampleService extends AbstractService
{
    protected function process($result)
    {
         $result->setSuccess('All done');
    }
}

这样接口实现了公共契约,通过AbstractService类实现了内部契约。应用程序只需在适用的情况下强制使用AbstractService 类。

【讨论】:

    【解决方案2】:

    NO,接口中的任何方法都不会有私有或受保护的访问标识符。

    **接口中声明的所有方法都必须是公共的;这就是接口的本质。

    关于界面的其他一些有趣的事实

    接口可以像类一样使用扩展操作符进行扩展。它们只能扩展其他接口。 (来源:https://www.php.net/manual/en/language.oop5.interfaces.php

    请注意,可以在接口中声明构造函数,这在某些情况下很有用,例如供工厂使用。子类中的签名应该相同。

    在您的情况下,另一个问题是 - 函数声明中缺少函数关键字。 应该是

    interface iService
    {
        public function method1();
    }
    

    【讨论】:

      【解决方案3】:

      在许多情况下,接口定义有助于其他模块保证类的行为和 API。在这些情况下,私有方法不是其他模块可以访问或理解的。这就是为什么您永远不能将私有方法放在接口上的原因。

      【讨论】:

        【解决方案4】:

        PHP manual page about interfaces 明确声明:

        接口中声明的所有方法都必须是公共的;这就是接口的本质。

        我想这解释了你得到的错误 ;-)

        【讨论】:

          【解决方案5】:

          接口是类型声明。类型是一组值,以及一组可以从外部对其进行的操作。私有方法不适合这张图片。

          interface T {
            public /*int*/ function f(array $a);
          }
          interface U {
            public /*T*/ function g(T $t);
          }
          
          class C implements U {
              public function g(T $t) {
                  ...
                  $x = $t->f();
                  ...
              }
          }
          

          接口很有用,因为它们声明了对象的接口。对象如何与其环境进行通信。

          现在假设T::f 可以声明为私有。这对其他对象有何用处?它不能从外部调用,它不会是其接口的一部分。

          【讨论】:

          • 同意...但它可以受到保护,对吧?由于抽象类允许...
          【解决方案6】:

          接口用于描述实现该接口的类的公共方法。接口中永远不能有私有方法。接口中的任何方法都假定正在使用中,不应更改。

          Interfaces 是 PHP 链接,但这是 OO 编程的标准。

          【讨论】:

          • 在 java 等其他语言中,您可以在接口中使用访问修饰符。
          【解决方案7】:

          通常一个接口只能有公共成员,因为接口的唯一功能是被继承。

          来自 PHPfreaks.com 教程:

          PHP5 具有接口。不应该 与接口混淆更多 一般意义上的接口关键字 创建一个可用于 强制执行一个通用接口 类而不必扩展它们 就像抽象类一样。取而代之的是 接口实现了。

          接口不同于抽象 类。一方面,它们实际上并不是 类。他们不定义属性, 他们没有定义任何行为。 接口中声明的方法 必须在类中声明 实施它。

          因为一个界面在更多 一般意义上是如何定义 对象与其他代码交互, 所有方法都必须声明为 public (请参阅本节中关于可见性的部分 章节)。使用抽象类, 抽象方法可以有任何 可见性,但扩展类 必须让他们的实现使用 相同(或更弱)的能见度。 实现一个接口会增加 方法作为抽象方法 主题类,未能实现它 将导致类似的错误 以下:

          致命错误:类 SomeConcreteClass 包含 n 个抽象方法并且必须 因此被宣布为抽象的或 实现剩下的方法是的, 抽象类可以实现 接口。

          【讨论】:

          • 太糟糕了。因为我希望有一个接口所需的公共方法,在抽象类中实现,该方法依赖于接口也强制执行的受保护方法。这样,抽象类可以提供公共接口,但要由子类来实现底层逻辑。有意义吗?
          • 似乎您希望子类实现的方法是抽象的。然后任何子类都必须实现它。但它与界面无关。
          猜你喜欢
          • 2011-07-09
          • 1970-01-01
          • 2011-03-21
          • 1970-01-01
          • 1970-01-01
          • 2015-11-22
          • 2013-01-18
          • 2012-01-09
          • 2023-03-04
          相关资源
          最近更新 更多