【问题标题】:How to prevent usage of public parent methods in child instance in PHP?如何防止在 PHP 的子实例中使用公共父方法?
【发布时间】:2014-09-09 09:51:01
【问题描述】:

假设我有名为 parent 和 child 的类,然后将从名为 caller.php 的 PHP 文件中使用它们

class Child extends Parent {

}

class Parent {

    public function parentMethod(){

    }
}

调用者.php

已阻止:

$child = new Child();
$child->parentMethod();

允许:

$parent = new Parent();
$parent->parentMethod();

我想阻止这样调用 parentMethod。但是如果我创建了 Parent 对象,我希望能够调用 parentMethod。有什么方法可以用来隐藏这个方法在子类中不公开,但仍然允许父对象公开调用这个方法?

到目前为止,我想出的唯一解决方案是保护这些方法,然后创建一个扩展父类的另一个类,然后为它需要的每个函数提供公共方法,但这听起来不太聪明。

【问题讨论】:

  • 没办法。理智的方式。根据定义,您使用了public,因此您将这些方法定义为随处可见。如果您想对子类隐藏父方法,请使用private - 但是这样的方法不会在任何地方看到,而是在该类本身。
  • 那么我应该让它们受保护并创建另一个类来调用所需的受保护方法吗?
  • protected 还不够。这意味着无处不在的可见性,包括子类。要对孩子隐藏方法,请使用private
  • 我的意思是,我必须能够调用外部的方法。就在这个子类案例中,我必须隐藏它。如果我有父对象,我希望能够在类外调用该函数。我认为我不应该创建父对象的任何实例。只需将其扩展到另一个类并创建一个将调用父方法的方法。
  • 听起来很荒谬。如果一个类extends 另一个类,那么该类的所有意图和目的都与父类相同,但可能在内部做更多或做一些不同的事情。但它仍然必须能够在可以使用父类的任何实例中完全替换父类。这就是里氏替换原则:en.wikipedia.org/wiki/SOLID。这是糟糕的 OOP 设计。

标签: php class inheritance parent-child visibility


【解决方案1】:

其实你应该问问自己:为什么你需要这样的限制?您已将方法定义为 public - 因此,您告诉 PHP 它应该在任何地方都可见。因此,为了防止子呼叫,您应该使用private 可见性定义。

有一种方法可以检查是否从父类进行调用,例如:

class ChildClass extends ParentClass {}

class ParentClass 
{

    public function parentMethod()
    {
       if(get_class($this) != __CLASS__)
       {
          throw new LogicException("Somehow due to business logic you're not allowed to call this from childs");
       }
    }
}

但我不建议这样做。原因是:

  • 可读性。你的方法只是普通的公共方法。展望它,不可能说您是否应该将它与子呼叫一起使用。因此,要维护这样的代码,您需要检查代码中的限制。现在想象一下,你有大约 50 种这样的方法。还有十几个这样的课程。
  • 可能会破坏Law of Demeter。为什么在使用这种限制时父类应该知道它的孩子?
  • 最后,这只是意外行为。从定义来看,任何人都会看到您正在扩展一个类。因此,根据定义,所有具有适当可见性的继承方法必须被继承。而你的逻辑改变了这一点。

你可能会想到composition,而不是继承。这可能是实现您的逻辑的正确方法(但是,由于我不了解整个背景,因此我无法确定)

【讨论】:

    【解决方案2】:

    您可以通过为您提到的两个类添加一个基父类来重新排列您的代码。像这样:

    class Base {
        public function inheritableMethod1() {}
        public function inheritableMethod2() {}
    }
    
    class Child extends Base {
    }
    
    class Parent extends Base {
        public function additionalMethod() {}
    }
    

    将所有可继承的方法从Parent 类移到Base,并只保留那些不能在Child 上调用的方法(在您的示例中为parentMethod)。

    基类可以选择是抽象的,以防止直接实例化它。

    【讨论】:

      【解决方案3】:

      检查抽象类是否适合您的需求: PHP: Class Abstraction

       class Child extends Parent {
                 public function parentMethod(
                    # Code
                 }
          }
          
          Abstract class Parent {
          
              abstract public function parentMethod();
          }
      

      【讨论】:

        猜你喜欢
        • 2011-04-11
        • 2011-07-26
        • 1970-01-01
        • 2019-03-29
        • 1970-01-01
        • 2012-12-05
        • 1970-01-01
        • 2017-02-27
        相关资源
        最近更新 更多