我试图为我的服务类创建一个通用接口。我在使用界面的两个班级时遇到了麻烦。他们共享一个名为create的方法。 create method除了三个参数。我希望它能够使第三个参数是可选的,这样两个类都可以使用它。
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){
//....
}
}
答案 0 :(得分:8)
这不是实现接口的正确方法。
首先,接口定义了如何使用类,可选参数可能会破坏这个原因。
除此之外,即使你有两个参数,它们也应该有自己的含义,这个意思应该是共享的。
接口方法签名之间存在巨大差异:
public static function create($var1, $var2);
和两个实现的方法:
public static function create($url, $server)
和
public static function create($methode, $url)
此外,实施这种方式的AFAIK会引起严格的标准违规,因为您正在更改界面签名。
如果您必须创建一个没有意义的共享界面,则没有理由共享或甚至创建界面。
答案 1 :(得分:4)
实现在父类或接口上定义为抽象签名的方法的类必须遵循某些规则,但它们不必完全匹配。
这个没有详细记录,例如PHP documentation of interfaces中甚至没有提到它,但是documentation of abstract classes触及了它:
此外,方法的签名必须匹配,即类型提示和所需参数的数量必须相同。例如,如果子类定义了一个可选参数,而抽象方法的签名没有,则签名中没有冲突。
换句话说,该方法必须能够根据签名进行调用,但不排除:
从问题中得知,这可行:
interface ServiceInterface{
public static function create($var1, $var2);
}
class ServiceObject1 implements ServiceInterface{
public static function create($url, $server){
//....
}
}
class ServiceObject2 implements ServiceInterface{
public static function create($methode, $url, $id = null){
//....
}
}
答案 2 :(得分:1)
在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
/ rant
对于抱怨OP想要做什么的用户-尽管一般的建议是这样做不是一个好主意,但在许多情况下,程序实际上并不关心预先设置的参数。例如,如果该函数是sumAll
而不是create
。
答案 3 :(得分:0)
你可以这样做:
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的实例。