是否可以为参数指定多个类型提示?

时间:2022-05-09 17:07:23

Is there a way to add more than one type hinting to a method? For example, foo(param) must receive a instance of string OR bar OR baz.

有没有办法添加多个类型提示方法?例如,foo(param)必须接收字符串OR bar OR baz的实例。

5 个解决方案

#1


25  

That is not possible to enforce (except inside the method). You can only provide a single type hint, and only to objects/interfaces and arrays (since PHP 5.1).

这是不可能强制执行的(除了方法内部)。您只能提供单个类型提示,并且只能提供对象/接口和数组(自PHP 5.1起)。

You can/should however document it in your method, i.e:

您可以/应该在您的方法中记录它,即:

/**
 * @param string|Bar|Baz $param1
 */
function foo($param1);

#2


14  

This is one use of interfaces. If you want to be sure that the object has a ->foobar($baz) method, you could expect an interface:

这是接口的一种用法。如果你想确保对象有一个 - > foobar($ baz)方法,你可以期待一个接口:

interface iFooBar {
    public function foobar($baz);
}

class Foo implements iFooBar {
    public function foobar($baz) { echo $baz; }
}
class Bar implements iFooBar {
    public function foobar($baz) { print_r($baz); }
}

function doSomething(iFooBar $foo) {
    $foo->foobar('something');
}

Then, when calling, these will work:

然后,在呼叫时,这些将起作用:

doSomething(new Foo());
doSomething(new Bar());

These will not:

这些不会:

doSomething(new StdClass());
doSomething('testing');

#3


9  

At the time of this writing there is no support for multiple explicit types. You have to rely on documentation and PHP's dynamic type system.

在撰写本文时,不支持多种显式类型。您必须依赖文档和PHP的动态类型系统。

However, I do have a mostly incomplete proposal for union types. It is targeting 7.NEXT (at the time of this writing this is 7.1) or 8 (whichever comes first).

但是,对于工会类型,我确实有一个大多不完整的提案。它的目标是7.NEXT(在撰写本文时为7.1)或8(以先到者为准)。

Here is a simple example of something that I think would be very valuable: array | Traversable:

这是一个我认为非常有价值的简单示例:array |穿越:

function map(callable $fn, array|Traversable $input) {
    foreach ($input as $key => $value) {
        yield $key => $fn($value);
    }
}

Unfortunately the RFC did not pass; however for the specific type array|Traversable there is now an iterable type which is exactly that.

不幸的是,RFC没有通过;但是对于特定类型数组| Traversable现在有一个可迭代类型,正是如此。

#4


6  

Type hinting only allows for one hint per parameter (and also, the hint needs to be array or a class name, you can't hint string), but you can do this by checking the type of the param within your function, using get_class:

类型提示只允许每个参数提示一个(而且,提示需要是数组或类名,你不能提示字符串),但你可以通过使用get_class检查函数中param的类型来做到这一点。 :

function foo($param)
{
  if (!(is_string($param) || in_array(get_class($param), array("Bar", "Baz")))
  {
    // invalid type for $param!
  }
}

You could even use trigger_error to have it fail with a PHP error (like it would if a type hint failed) if you wanted.

您甚至可以使用trigger_error使其失败并出现PHP错误(如果您需要,则会出现类型提示失败)。

#5


5  

Fantastic question. It applies to both IDE documentation and PHP 5 Type Hinting. You have to remember that in OO polymorphism is your friend.

很棒的问题。它适用于IDE文档和PHP 5类型提示。你必须记住,OO多态性是你的朋友。

If you create a base class and extend them, your type hint will be base class... all extended class will work. See example below.

如果您创建基类并扩展它们,您的类型提示将是基类...所有扩展类都将起作用。见下面的例子。

//
$test = new DUITest();

//  Calls below will work because of polymorphism
echo $test->test(new Molecule()) . '<br/>';
echo $test->test(new Vodka()) . '<br/>';
echo $test->test(new Driver()) . '<br/>';
echo $test->test(new Car()) . '<br/>';

//  Will not work because different data type
echo $test->test(new Pig()) . '<br/>';
echo $test->test(new Cop()) . '<br/>';
echo $test->test('test') . '<br/>';
echo $test->test(array()) . '<br/>';



/**
 * Class to test 
 */
class DUITest {

    public function __construct() {
        ;
    }

    /**
     * Using type-hinting
     * 
     * See below link for more information
     * @link http://www.php.net/manual/en/language.oop5.typehinting.php
     * 
     * @param Molecule|Car|Driver|Vodka $obj 
     */
    public function test(Molecule $obj) {
        echo $obj;
    }

}

/**
 * Base Class
 */
class Molecule {

    public function __construct() {}

    /**
     * Outputs name of class of current object
     * @return <type> 
     */
    public function __toString() {
        return get_class($this);
    }

}

class Car extends Molecule {}

class Driver extends Molecule {}

class Vodka extends Molecule {}

class Pig {}
class Cop extends Pig{}

#1


25  

That is not possible to enforce (except inside the method). You can only provide a single type hint, and only to objects/interfaces and arrays (since PHP 5.1).

这是不可能强制执行的(除了方法内部)。您只能提供单个类型提示,并且只能提供对象/接口和数组(自PHP 5.1起)。

You can/should however document it in your method, i.e:

您可以/应该在您的方法中记录它,即:

/**
 * @param string|Bar|Baz $param1
 */
function foo($param1);

#2


14  

This is one use of interfaces. If you want to be sure that the object has a ->foobar($baz) method, you could expect an interface:

这是接口的一种用法。如果你想确保对象有一个 - > foobar($ baz)方法,你可以期待一个接口:

interface iFooBar {
    public function foobar($baz);
}

class Foo implements iFooBar {
    public function foobar($baz) { echo $baz; }
}
class Bar implements iFooBar {
    public function foobar($baz) { print_r($baz); }
}

function doSomething(iFooBar $foo) {
    $foo->foobar('something');
}

Then, when calling, these will work:

然后,在呼叫时,这些将起作用:

doSomething(new Foo());
doSomething(new Bar());

These will not:

这些不会:

doSomething(new StdClass());
doSomething('testing');

#3


9  

At the time of this writing there is no support for multiple explicit types. You have to rely on documentation and PHP's dynamic type system.

在撰写本文时,不支持多种显式类型。您必须依赖文档和PHP的动态类型系统。

However, I do have a mostly incomplete proposal for union types. It is targeting 7.NEXT (at the time of this writing this is 7.1) or 8 (whichever comes first).

但是,对于工会类型,我确实有一个大多不完整的提案。它的目标是7.NEXT(在撰写本文时为7.1)或8(以先到者为准)。

Here is a simple example of something that I think would be very valuable: array | Traversable:

这是一个我认为非常有价值的简单示例:array |穿越:

function map(callable $fn, array|Traversable $input) {
    foreach ($input as $key => $value) {
        yield $key => $fn($value);
    }
}

Unfortunately the RFC did not pass; however for the specific type array|Traversable there is now an iterable type which is exactly that.

不幸的是,RFC没有通过;但是对于特定类型数组| Traversable现在有一个可迭代类型,正是如此。

#4


6  

Type hinting only allows for one hint per parameter (and also, the hint needs to be array or a class name, you can't hint string), but you can do this by checking the type of the param within your function, using get_class:

类型提示只允许每个参数提示一个(而且,提示需要是数组或类名,你不能提示字符串),但你可以通过使用get_class检查函数中param的类型来做到这一点。 :

function foo($param)
{
  if (!(is_string($param) || in_array(get_class($param), array("Bar", "Baz")))
  {
    // invalid type for $param!
  }
}

You could even use trigger_error to have it fail with a PHP error (like it would if a type hint failed) if you wanted.

您甚至可以使用trigger_error使其失败并出现PHP错误(如果您需要,则会出现类型提示失败)。

#5


5  

Fantastic question. It applies to both IDE documentation and PHP 5 Type Hinting. You have to remember that in OO polymorphism is your friend.

很棒的问题。它适用于IDE文档和PHP 5类型提示。你必须记住,OO多态性是你的朋友。

If you create a base class and extend them, your type hint will be base class... all extended class will work. See example below.

如果您创建基类并扩展它们,您的类型提示将是基类...所有扩展类都将起作用。见下面的例子。

//
$test = new DUITest();

//  Calls below will work because of polymorphism
echo $test->test(new Molecule()) . '<br/>';
echo $test->test(new Vodka()) . '<br/>';
echo $test->test(new Driver()) . '<br/>';
echo $test->test(new Car()) . '<br/>';

//  Will not work because different data type
echo $test->test(new Pig()) . '<br/>';
echo $test->test(new Cop()) . '<br/>';
echo $test->test('test') . '<br/>';
echo $test->test(array()) . '<br/>';



/**
 * Class to test 
 */
class DUITest {

    public function __construct() {
        ;
    }

    /**
     * Using type-hinting
     * 
     * See below link for more information
     * @link http://www.php.net/manual/en/language.oop5.typehinting.php
     * 
     * @param Molecule|Car|Driver|Vodka $obj 
     */
    public function test(Molecule $obj) {
        echo $obj;
    }

}

/**
 * Base Class
 */
class Molecule {

    public function __construct() {}

    /**
     * Outputs name of class of current object
     * @return <type> 
     */
    public function __toString() {
        return get_class($this);
    }

}

class Car extends Molecule {}

class Driver extends Molecule {}

class Vodka extends Molecule {}

class Pig {}
class Cop extends Pig{}