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

时间:2021-01-22 22:32:47

I have a base class in which I want to specify the methods a child class must have, but not implement them itself. However, the methods in a child class may have a different number of paramaters to the definition in the base class.

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

Having tried this with an abstract method, php doesn't allow this. Is it possible?

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

4 个解决方案

#1


3  

Short of specifying the abstract method with no parameters and requiring the subclassed method to access the args through func_get_args, I don't see how this would be possible.

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

#2


6  

The child class's function can add extra, optional arguments to the signature without it causing errors:

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

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

class NewFoo extends Foo {

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

#3


1  

I would say this is one of the weak points of PHP's object orientation, that it wasn't designed to handle this kind of use case. It just wasn't meant to allow overloaded methods for its

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

It is indeed possible to do what you're talking about as a kind of hack, in both the way mentioned above with:

确实有可能以上面提到的方式执行你正在谈论的一种黑客攻击:

func_get_args()

or, just (like the commenter mentioned) pass in an array of arguments. Alternately you could pass in an object that has your arguments as data members. Then you could extend the parameter/argument object for your child method.

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

The point is that PHP is a language that thrives on permissiveness and not restriction. Abstract classes have a very basic implementation in PHP. If you have the need for a lot of structure like this, then PHP really might not be the best language choice.

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

#4


0  

I don't think this is an answer that you will want to use in production as it will be fairly slow, but just for the sake of it I tried to write something using Reflection, which seems to work. You will still get an E_STRICT because method declarations in subclasses are apparently supposed to match.

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

#1


3  

Short of specifying the abstract method with no parameters and requiring the subclassed method to access the args through func_get_args, I don't see how this would be possible.

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

#2


6  

The child class's function can add extra, optional arguments to the signature without it causing errors:

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

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

class NewFoo extends Foo {

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

#3


1  

I would say this is one of the weak points of PHP's object orientation, that it wasn't designed to handle this kind of use case. It just wasn't meant to allow overloaded methods for its

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

It is indeed possible to do what you're talking about as a kind of hack, in both the way mentioned above with:

确实有可能以上面提到的方式执行你正在谈论的一种黑客攻击:

func_get_args()

or, just (like the commenter mentioned) pass in an array of arguments. Alternately you could pass in an object that has your arguments as data members. Then you could extend the parameter/argument object for your child method.

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

The point is that PHP is a language that thrives on permissiveness and not restriction. Abstract classes have a very basic implementation in PHP. If you have the need for a lot of structure like this, then PHP really might not be the best language choice.

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

#4


0  

I don't think this is an answer that you will want to use in production as it will be fairly slow, but just for the sake of it I tried to write something using Reflection, which seems to work. You will still get an E_STRICT because method declarations in subclasses are apparently supposed to match.

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