我有这样的界面:
public interface ISmsService {
//method for vendor A
String sendSms();
//method for vendorB
int sendSms(String loginid);
}
该接口描述了两个供应商的重载方法。
我有一个像这样的供应商实现:
public class VendorAService implements ISmsService{
@Override
public String sendSms() {
return "send msg via vendor A";
}
//I want to restrict the usage of this method for vendor B instance at compile time
@Override
public int sendSms(String loginid) {
//I can throw an exception but I do not want to restrict it at runtime.
return 0;
}
}
这样的供应商B实现:
public class VendorBService implements ISmsService{
//I want to restrict the usage of this method for vendor A instance at compile time
@Override
public String sendSms() {
//I can throw an exception but I do not want to restrict it at runtime
return null;
}
@Override
public int sendSms(String loginid) {
return 1000;
}
}
我的实施者课程是这样的:
public class User {
public static void main(String[] args) {
ISmsService smsService = new VendorAService();
smsService.sendSms("12345"); // I want thiş line gives a compile time error. I want only a vendorB type can call this method.
smsService = new VendorBService();
smsService.sendSms(); //Same here. I just want vendorA type can call sendSms method without a String parameter
}
}
正如我在评论行中描述的那样,我想指定一个供应商实例只能调用一个特定的方法。我可以在运行时抛出错误的供应商调用之类的异常。但是如果有可能我想在编译时限制行为。
有人遇到过这种问题吗?
春天有解决方法吗?
提前致谢
答案 0 :(得分:4)
如果您不希望用户能够调用错误的方法,并且您希望编译器为您进行检查,则解决方案非常简单:完全删除接口ISmsService
。在您的情况下,它根本没有帮助,引入偶然的复杂性,而不提供任何简化作为回报。接口的用户需要在供应商之间保持差异化,即使他们提供了一个可以消除差异的接口。
如果你想获得界面的好处,你应该以某种方式统一这两种方法,让用户调用接口方法,而不用考虑后面的哪个供应商。例如,您可以这样做:
class SmsParameters {
... // Add methods to set parameters, in some non-restrictive way.
... // In particular, users should be able to pass login parameters through it
}
class SmsReturn {
... // Add methods to harvest the return value, e.g. as an Object
}
interface ISmsService {
SmsReturn sendSms(SmsParameters args);
}
编译器可以在将供应商与呼叫者匹配方面做得不多,但至少调用者只能调用一种方法。
答案 1 :(得分:1)
接口应分为两个不同的接口,每个接口包含一个方法。第一个类应该只实现第一个接口,第二个类应该只实现第二个接口。
答案 2 :(得分:1)
我建议改变这样的界面
public interface ISmsService {
// Common method, with optional parameter
Object sendSms(String...loginid);
}
然后实现可能是
public class VendorAService implements ISmsService{
@Override
public Object sendSms(Strong...loginid) {
// here you can use the parameter
return "send msg via vendor A";
}
}
和
public class VendorBService implements ISmsService{
@Override
public Object sendSms(Strong...loginid) {
// here you can ignore the parameter
return 1000;
}
}
由于参数是可选的,因此可以使用
ISmsService smsService = new VendorAService();
smsService.sendSms("12345");
smsService = new VendorBService();
smsService.sendSms();
smsService.sendSms("random-string"); // not important but, this would work without causing any problems