当前位置:  开发笔记 > 编程语言 > 正文

在PHP 7中键入提示 - 对象数组

如何解决《在PHP7中键入提示-对象数组》经验,为你挑选了3个好方法。

也许我错过了一些东西,但有没有选项来定义该函数应该有参数或返回例如User对象的数组?

请考虑以下代码:

name = $name;
        $this->age = $age;
    }

    /**
     * @return mixed
     */
    public function getName() : string
    {
        return $this->name;
    }

    public function getAge() : int
    {
        return $this->age;
    }
}

function findUserByAge(int $age, array $users) : array
{
    $result = [];
    foreach ($users as $user) {
        if ($user->getAge() == $age) {
            if ($user->getName() == 'John') {
                // complicated code here
                $result[] = $user->getName(); // bug
            } else {
                $result[] = $user;
            }
        }
    }

    return $result;
}

$users = [
    new User('John', 15),
    new User('Daniel', 25),
    new User('Michael', 15),
];

$matches = findUserByAge(15, $users);

foreach ($matches as $user) {
    echo $user->getName() . ' '.$user->getAge() . "\n";
}

PHP7中是否有任何选项告诉函数findUserByAge应该返回用户数组?我希望当添加类型提示时,它应该是可能的,但我没有找到任何关于对象数组的类型提示的信息,所以可能它不包含在PHP 7中.如果它不包括在内,你有没有任何线索为什么它是添加类型提示时不包含?



1> Fabian Schme..:

它不包括在内.

如果它不包括在内,你有没有任何线索为什么在添加类型提示时不包括它?

使用当前的数组实现,它需要在运行时检查所有数组元素,因为数组本身不包含类型信息.

它实际上已经被提议用于PHP 5.6但被拒绝:RFC"arrayof" - 有趣的是,并不是因为性能问题被证明是可以忽略的,而是因为没有就应该如何实现它达成一致.还有人反对在没有标量类型提示的情况下它是不完整的.如果您对整个讨论感兴趣,请在邮件列表存档中阅读.

IMHO数组类型提示将与类型化数组一起提供最大的好处,我很乐意看到它们实现.

所以也许是时候换新RFC了,重新开始讨论.


部分解决方法:

您可以键入提示可变参数,从而将签名写为

function findUserByAge(int $age, User ...$users) : array

用法:

findUserByAge(15, ...$userInput);

在这个调用中,参数$userInput将被"解包"为单个变量,并且在方法本身中"打包"回一个数组$users.每个项目都经过验证,属于类型User.$userInput也可以是迭代器,它将被转换为数组.

遗憾的是,返回类型没有类似的解决方法,您只能将它用于最后一个参数.


对于IDE,您可以使用phpDoc` @return User []`
当您以显示的方式使用可变参数时,是否有人测量了性能缺陷?
@RobertLimanto不,并且在7.2中仍不可见,请查看https://wiki.php.net/rfc#php_next_72

2> Steini..:

由于数组可以包含混合值,因此这是不可能的.

您必须为此目的使用对象/类.

您可以创建一个类来管理自己的列表数组(私有/受保护属性),并拒绝添加其他值作为此问题的工作范围(如果确实需要).

但是,没有负责任的程序员会破坏预期的模式,尤其是如果你正确地评论它.无论如何,它将在程序中发生错误时被识别.

出院:

例如,您可以创建任何数组:

$myArray = array();

并添加一个数字:

$myArray[] = 1;

一个字符串:

$myArray[] = "abc123";

和一个对象

$myArray[] = new MyClass("some parameter", "and one more");

另外不要忘记,您可以拥有一个简单的数组,一个多维堆叠数组以及可以具有混合模式的关联数组.

很难找到一个解析器/ nottation来使所有版本都能使用强制我认为的数组格式的表达式.

一方面很酷,但是在奖牌的另一方面你会失去一些混合数据的能力,这对于很多现有代码和PHP必须提供的灵活性至关重要.

由于混合内容是我们在PHP 7中不想错过的功能,因此无法键入提示数组的确切内容,因为您可以放入任何内容.



3> 小智..:

我给一般的答案有关数组的类型提示。

我对所选答案进行了修改。主要区别在于参数是一个数组,而不是被检查类的许多实例。

/**
 * @param $_foos Foo[]
 */
function doFoo(array $_foos)
{return (function(Foo ...$_foos){

    // Do whatever you want with the $_foos array

})(...$_foos);}

看起来有点模糊,但是很容易理解。并非总是在每次调用时都手动解压缩数组,而是调用函数内部的闭包,并将数组解压缩为参数。

function doFoo(array $_foos)
{
    return (function(Foo ...$_foos){ // Closure

    // Do whatever you want with the $_foos array

    })(...$_foos); //Main function's parameter $_foos unpacked
}

我觉得这很酷,因为您可以像使用具有ArrayOfType参数的任何其他语言函数一样使用该函数。另外,该错误的处理方式与其余PHP类型提示错误的处理方式相同。此外,您不会混淆其他程序员,他们会使用您的函数,并且不得不拆开它们的数组,这总是让人感到有些棘手。

您确实需要一点编程经验,以了解其工作原理。如果您需要多个参数,则可以始终在闭包的“使用”部分添加它们。

您也可以使用文档注释来公开类型提示。

/**
 * @param $_foos Foo[] <- An array of type Foo
 */

这是一个OO示例:

class Foo{}

class NotFoo{}

class Bar{
    /**
     * @param $_foos Foo[]
     */
    public function doFoo(array $_foos, $_param2)
    {return (function(Foo ...$_foos) use($_param2){

        return $_param2;

    })(...$_foos);}
}

$myBar = new Bar();
$arrayOfFoo = array(new Foo(), new Foo(), new Foo());
$notArrayOfFoo = array(new Foo(), new NotFoo(), new Foo());

echo $myBar->doFoo($arrayOfFoo, 'Success');
// Success

echo $myBar->doFoo($notArrayOfFoo, 'Success');
// Uncaught TypeError: Argument 2 passed to Bar::{closure}() must be an instance of Foo, instance of NotFoo given...

注意:这也适用于非对象类型(int,字符串等)

推荐阅读
乐韵答题
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有