我可以为子类指定非严格的方法要求吗?

时间:2008-12-12 03:47:59

标签: php oop abstract-class

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

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

4 个答案:

答案 0 :(得分:6)

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

abstract class Foo {
  abstract function bar($a);
}

class NewFoo extends Foo {

  function bar($a, $b = null) {
    //do something
  }
}

答案 1 :(得分:3)

如果没有参数指定抽象方法并且要求子类方法通过func_get_args访问args,我不知道这是怎么回事。

答案 2 :(得分:1)

我认为这是PHP面向对象的弱点之一,它不是为处理这种用例而设计的。它本身并不意味着允许重载方法

确实有可能以上述方式执行你所说的任何一种黑客攻击:

func_get_args()

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

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

答案 3 :(得分:0)

我不认为这是你想要在制作中使用的答案,因为它会相当慢,但只是为了它,我试图用反射写一些东西,这似乎有效。你仍然会得到一个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();