【问题标题】:Weird issue with parameter validation on usage of interface implementation关于接口实现使用的参数验证的奇怪问题
【发布时间】:2020-01-08 04:46:55
【问题描述】:

所以基本上我不确定这是解析我的代码的 PhpStorm 问题,还是 PHP 和接口的奇怪怪癖,但基本上我有以下接口

<?php

namespace App\Contracts;

/**
 * Interface IFileSource
 * @package App\Contracts
 */
interface IFileSource
{
    public function getFilesByPattern(string $filePattern) : array;
}

使用以下实现

<?php

namespace App\Sources;

use App\Contracts\IFileService;
use App\Services\File\FileService;

/**
 * Class FileSource
 * @package App\Sources
 */
class FileSource implements IFileSource
{
    /**
     * @var FileService
     */
    private $fileService;

    public function __construct (IFileService $fileService)
    {
        $this->fileService = $fileService;
    }


    /**
     * @param string $filePattern
     * @return File[]
     * NOTE THIS ASSUMES FILESYSTEM
     */
    public function getFilesByPattern (string $filePattern) : array
    {
        $filesDetails = $this->fileService->getFilesByPattern($filePattern);
        return [];
    }
}

及用途

<?php

namespace App\Console\Commands;

use App\Contracts\IFileSource;
use App\Sources\FileSource;

class ImportXML extends Command
{

    /**
     * @var FileSource
     */
    protected $fileSource;

    public function __construct (IFileSource $fileSource)
    {
        parent::__construct();
        $this->fileSource = $fileSource;
    }

    public function handle () : void
    {     
            $filePattern = 'APATTERN';
            $files = $this->fileSource->getFilesByPattern($filePattern)
    }
}

我的问题与此实现的用法有关。

所以下面是一个有效的用法:

$filePattern = 'APATTERN';
$this->fileSource->getFilesByPattern(filePattern)

但由于某种原因,以下也被视为有效用法?

$filePattern = 'APATTERN';
$this->fileSource->getFilesByPattern(filePattern,filePattern,filePattern,filePattern,filePattern,filePattern,filePattern)

为什么它不在乎我不符合我的实现?

【问题讨论】:

  • 始终提供真实的代码示例,可以轻松复制粘贴并在本地进行测试。在我的代码中,它总是将其突出显示为错误。但是我的代码可能和你的不同......
  • 哈哈,对不起,但现在我认为我们应该尝试Minimal, Complete and Verifiable Example,强调最小
  • 如果你使用 IFileSource 而不是 FileSource,PhpStorm 将正确报告警告(好吧,至少在我的测试项目中没有 Laravel 代码和 PHP 语言级别设置为 7.2,如果那样的话做任何差异)。 postimg.cc/qzk82jp5。如果我在 PHPDoc typehint 中为字段和构造函数参数使用FileSource 也可以工作(所以在两个方面都是一样的)
  • 不能说到底为什么在同时使用接口和具体类类型提示时它不报告错误(IDE 看到 2 个可能的签名:虽然它们是相同的......有 2 个...)。可能是错误或 IDE 特定限制 - 检查/报告至 youtrack.jetbrains.com/issues/WI
  • 您的代码没问题——没有问题。但是,如果您正在使用接口(作为参数类型提示)......那么在其他地方也使用接口(通过 PHPDoc 的字段类型提示)。如果正在使用接口,则使用特定类进行类型提示没有多大意义(无需混合它们)。

标签: php laravel interface phpstorm


【解决方案1】:

为什么它不在乎我不符合我的实现

这就是接口的全部意义——它们不关心实现。他们只关心方法是如何定义的,以及 signature 是否符合接口。

但是,我认为这里要问的真正问题是为什么 PHP 解释器 在将多个参数传递给函数时不会抛出异常。答案是因为这就是 PHP 实现重载的方式。它们允许传递可变数量的参数,您可以使用 func_get_args 等函数访问这些参数。

您绝对应该阅读https://www.php.net/manual/en/functions.arguments.php#functions.variable-arg-list 并查看新的(ish)splat 运算符...

类似的质量保证

【讨论】:

  • 谢谢!所以也许我应该问的真正问题是有没有办法禁用实现的方法重载?我的印象是,如果您需要此类功能的另一个版本,因为这表明您需要更新实现/接口的设计。所以在我的情况下,如果我需要 getFilesByPattern 也将文件路径与文件名分开,我会创建一个 getFilesByPatternAndPath 而不是增加 getFilesByPattern 的复杂性来支持重载参数?也许我想得太小了……
【解决方案2】:

所以万一其他人偶然发现了这个,

感谢 LazyOne 帮助解释我做错了什么

这是由于我在 PHPdoc 中执行实现而不是依赖接口来执行类型提示(或将接口添加为类型提示而不是实现),一旦我更改了它就开始抱怨正如预期的那样。

当接口的重点是强制执行这些事情时,为什么要强制执行。

呵呵

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-27
    • 2019-08-28
    • 2013-05-17
    • 1970-01-01
    • 2011-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多