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