【问题标题】:Can I specify a non strict method requirement for child classes?我可以为子类指定非严格的方法要求吗?
【发布时间】:2008-12-12 03:47:59
【问题描述】:

我有一个基类,我想在其中指定子类必须具有的方法,但不自己实现它们。但是,子类中的方法可能与基类中的定义具有不同数量的参数。

用抽象方法尝试过,php 不允许这样做。有可能吗?

【问题讨论】:

    标签: php oop abstract-class


    【解决方案1】:

    子类的函数可以向签名添加额外的可选参数,而不会导致错误:

    abstract class Foo {
      abstract function bar($a);
    }
    
    class NewFoo extends Foo {
    
      function bar($a, $b = null) {
        //do something
      }
    }
    

    【讨论】:

      【解决方案2】:

      没有指定没有参数的抽象方法并要求子类方法通过func_get_args访问args,我不明白这怎么可能。

      【讨论】:

      • 这样做的另一面是只接受一个参数,并要求所有参数都通过数组传入。
      【解决方案3】:

      我会说这是 PHP 面向对象的弱点之一,它不是为处理这种用例而设计的。它只是不打算允许它的重载方法

      确实有可能以上述两种方式将您所说的作为一种 hack 进行:

      func_get_args()
      

      或者,只是(就像评论者提到的)传入一个参数数组。或者,您可以传入一个将您的参数作为数据成员的对象。然后你可以为你的子方法扩展参数/参数对象。

      重点是 PHP 是一种以宽容而非限制为基础的语言。抽象类在 PHP 中有一个非常基本的实现。如果你需要很多这样的结构,那么 PHP 可能真的不是最好的语言选择。

      【讨论】:

        【解决方案4】:

        我不认为这是您想要在生产中使用的答案,因为它会相当慢,但为了它,我尝试使用 Reflection 编写一些东西,这似乎有效。您仍然会得到 E_STRICT,因为子类中的方法声明显然应该匹配。

        class a {
            protected $requiredMethodsInSubclass = array( 'method1', 'method2', 'method3' );
        
            public function __construct() {
                $reflObject = new ReflectionObject($this);
        
                $className = $reflObject->getName();
        
                if ($className == __CLASS__) {
                    //this class is being instanciated directly , so don't worry about any subclasses
                    return;
                }
        
                foreach ($this->requiredMethodsInSubclass as $methodName) {
                    try {
                        $reflMethod = $reflObject->getMethod($methodName);
                    } catch (ReflectionException $e) { //method not anywhere
                        trigger_error("Method $methodName is not declared in class " . __CLASS__ . " or subclass $className", E_USER_ERROR);
                        continue;
                    }
        
                    $declaringClass =  $reflMethod->getDeclaringClass();
        
                    if ($declaringClass->getName() == __CLASS__) {
                        //method is declared in this class, not subclass
                       trigger_error("Method $methodName is not declared in subclass $className", E_USER_ERROR);
                    }
                }
            }
        
            public function method1() {
        
            }
        
            public function method2($a) {
        
            }
         }
        
        
        
        class b extends a {
            public function __construct() {
                parent::__construct();
        
                //some stuff
            }
        
        
            public function method2($a, $b, $c) {
        
            }
        
        }
        
        
        
        $b = new b();
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-11-04
          • 2011-03-11
          • 1970-01-01
          • 2013-07-28
          • 2011-08-26
          • 1970-01-01
          • 2019-03-15
          • 1970-01-01
          相关资源
          最近更新 更多