Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP接口可选参数_Php_Oop_Interface - Fatal编程技术网

PHP接口可选参数

PHP接口可选参数,php,oop,interface,Php,Oop,Interface,我正在尝试为我的服务类创建一个通用接口。我在两个类使用接口时遇到问题。他们共享一个名为create的方法。create方法不包含三个参数。我希望它使第三个参数是可选的,这样两个类都可以使用它 interface ServiceInterface{ public static function create($var1, $var2, $thisOneIsOptional); } class ServiceObject1 implements ServiceInterface{

我正在尝试为我的服务类创建一个通用接口。我在两个类使用接口时遇到问题。他们共享一个名为create的方法。create方法不包含三个参数。我希望它使第三个参数是可选的,这样两个类都可以使用它

interface ServiceInterface{

    public static function create($var1, $var2, $thisOneIsOptional);

}

class ServiceObject1 implements ServiceInterface{

    public static function create($url, $server){
       //....
    }
 }

class ServiceObject2 implements ServiceInterface{

    public static function create($methode, $url, $id){
       //....
    }
}

这不是实现接口的正确方法

首先,一个接口定义了类应该如何使用,一个可选参数可能会破坏这个原因

除此之外,即使您有两个参数,它们也应该有自己的含义,并且这个含义应该共享

接口方法签名之间存在巨大差异:

public static function create($var1, $var2);
以及两种实施方法:

public static function create($url, $server)
以及:

另外,AFAIK,实现这种方式将导致严格的标准冲突,因为您正在更改接口签名

如果您必须创建一个毫无意义的共享接口,则没有理由共享甚至创建该接口。您可以:

interface ServiceInterface{

    public static function create($url, $server, $id = null);

}

class ServiceObject1 implements ServiceInterface{

    public static function create($url, $server, $id = null){
       //....
    }
}

class ServiceObject2 implements ServiceInterface{

    public static function create($methode, $url, $id = null){
       //....
    }
}

但是让ServiceObject2扩展ServiceObject1不是更容易、更符合逻辑吗?通过这样做,您可以用一个额外的参数覆盖函数。而不是要求对象是接口的实例,而是要求它是ServiceObject1的实例。

实现父类或接口上定义为抽象签名的方法的类必须遵循某些规则,但它们不必完全匹配

这没有很好的文档记录,例如,在中甚至没有提到,但被以下内容所触及:

此外,方法的签名必须匹配,即类型提示和所需参数的数量必须相同。例如,如果子类定义了可选参数,而抽象方法的签名没有,则签名中没有冲突

换句话说,该方法必须能够根据签名进行调用,但不排除:

  • 在方法的实现中使用不同的变量名
  • 在方法签名中声明的参数(如果有)之后声明其他可选参数
  • 从问题中可以看出,这将起到以下作用:

    接口服务接口{
    公共静态函数create($var1,$var2);
    }
    类ServiceObject1实现ServiceInterface{
    公共静态函数create($url$server){
    //....
    }
    }
    类ServiceObject2实现ServiceInterface{
    公共静态函数create($methode,$url,$id=null){
    //....
    }
    }
    
    在PHP 56+中,可以使用省略号运算符:

    interface ServiceInterface {
        public static function create(...$params);
    }
    
    class ServiceObject1 implements ServiceInterface
    {
        public static function create(...$params)
        {
            $url = $params[0];
            $server = $params[1];
            print "url = $url\n";
            print "server = $server\n";
        }
    }
    
    class ServiceObject2 implements ServiceInterface
    {
        public static function create(...$params)
        {
            $method = $params[0];
            $url = $params[1];
            $id = $params[1];
            print "method = $method\n";
            print "url = $url\n";
            print "id = $id\n";
        }
    }
    print "ServiceObject1::create\n";
    ServiceObject1::create("url", "server");
    print "\nServiceObject2::create\n";
    ServiceObject2::create("method", "url", "id");
    
    输出:

    ServiceObject1::create
    url = url
    server = server
    
    ServiceObject2::create
    method = method
    url = url
    id = url
    
    /咆哮


    对于抱怨OP想要做什么的用户,一般的建议是这样做是不好的,但在许多情况下,程序实际上并不关心预先设置的参数。例如,如果函数是
    sumAll
    ,而不是
    create

    ,那么拥有一个允许以不同方式使用方法的界面听起来有点违反直觉。接口的全部目的是确切地知道如何使用实现类。如果一个服务不需要
    $id
    ,但另一个需要,则仍然需要它。然后就由服务来忽略它了;或者如果数组公共静态函数create($var1,$var2,$thisOneIsOptional=[]);您不能有一个带有可选参数的接口和一个需要它的实现——这意味着签名不兼容。如果您不能充分概括您的接口以适合所有可能的实现,那么接口就不是您想要的。如果您没有实际查看每个服务的代码,您就不知道每个服务需要或不需要哪些参数。那么,为什么还要麻烦接口呢?
    static
    方法的接口……无论如何都很奇怪。根据接口编码意味着您可以用对象替换其他对象。但是,静态方法总是在特定的类上调用,不能被注入/替换。那么…为什么一开始就有一个界面?是的,我可以做到。我计划为我目前使用的所有模型(6个模型)创建一个服务类,并不是每个模型都有相同数量的create方法参数。我想为他们所有人签订一份合同会很好。但是制作一个超类是一个很好的解决方案。只是界面在结构上更漂亮:)@melkawakibi-只是一个建议;你应该考虑编写直观的代码,而不是思考什么是“漂亮的”,“酷孩子使用什么”或添加“仅仅因为”的东西。在我看来,这更漂亮。这真是一个有洞察力的研究,谢谢!看来php文档应该修改了。您知道吗,您还可以将返回类型添加到具有没有返回类型的接口的实现中?e、 g.接口定义
    公共函数foo()和实现可以添加
    字符串
    返回类型,并且仍然兼容
    公共函数foo():string{return'bar';}
    @KelvinJones,你说得对,我收回我的评论!我对此投了更高的票,因为它实际上回答了OP的问题,但仍然提到这无论如何都不是最佳实践。我正在开发一个遗留代码库,在这里我需要扩展几个实现接口的类。即使这违反了接口的纯粹概念,这也是实现这一目标的最少中断和最快的方法。在我的场景中,最初的作者应该创建一个实现接口的抽象类,然后让所有内容都继承自抽象类。然而,
    允许我修改大约12个类,而不是50多个类。这是一场胜利。
    ServiceObject1::create
    url = url
    server = server
    
    ServiceObject2::create
    method = method
    url = url
    id = url