如何创建具有可变参数/不同方法签名的方法接口?
Posted
技术标签:
【中文标题】如何创建具有可变参数/不同方法签名的方法接口?【英文标题】:How to create method interface with variable parameters / different method signatures? 【发布时间】:2011-09-01 03:40:55 【问题描述】:我正在尝试创建一个通用类的接口,但实现类可以有不同的参数。
例如
public interface IViewModel
//...
void ResetReferences();
// and then, in my class implementations, something like this:
public class LocationViewModel : IViewModel
public void ResetReferences(List<StateProvinces> stateProvinces) //...
public class ProductViewModel : IViewModel
public void ResetReferences(List<Color> colors, List<Size> sizes) //...
所以请注意,我想标准化 ResetReferences
命名约定。我很确定我不能这样做,但是有没有可行的设计模式?例如在我的界面中,如下所示?
// variable parameters
void ResetReferences(params object[] list);
但是我该如何进行类型检查或让它调用我想要的实际方法签名等?
也许接口是错误的使用方式?也许只是一个基类和一些编码约定?
谢谢,
【问题讨论】:
【参考方案1】:用实现相关接口的对象替换您的 args 列表:
public interface IViewModel
//...
void ResetReferences(IResetValues vals);
我应该补充一点,IMO,ResetReferences()
不应该接受参数......它应该重置为特定于实现您的接口的各个类型的默认值......“重置”是这个词对我来说意味着“恢复到初始状态”...添加 args 意味着您可以控制它。
【讨论】:
我喜欢你的方法,谢谢。顺便说一句,我已将该方法重命名为“SetReferences”:) @Raymond:如果您喜欢这个答案,请点赞,并给 JeffSahol 10 更多声望点。人们欣赏“谢谢”评论,但在追求声誉的过程中,评论无济于事。【参考方案2】:您必须在接口中同时拥有这两种方法(并且让一个不正确的方法对实例抛出不受支持的异常),或者让接口从其他两个接口继承以达到相同的效果。
接口定义是整个签名。
也可以将对象作为参数传递(可能从 ParameterProvider 基类派生),以便对象封装动态特性并仍然允许接口是静态的。但那一点你基本上是在围绕类型系统工作。
【讨论】:
【参考方案3】:如果参数可以不同,那么它就不是一个真正的通用接口。这么说吧:调用者需要知道实现类吗?如果是这样,您就失去了接口的松散耦合优势。
一种选择是将参数封装到另一种类型中,并使该类在该类型上通用。例如:
public interface IViewModel<T>
void ResetReferences(T data);
然后您将List<Color> colors, List<Size> sizes
封装为一种类型,并可能将List<StateProvinces> stateProvinces
放入另一种类型中。
虽然有点尴尬……
【讨论】:
“虽然有点尴尬……” 解决这个问题最理想的方法是什么? @b1nary.atr0phy:理想情况下“不要让自己陷入这种情况”。鉴于信息有限,我已经给出了我能给出的最佳答案——它非常敏感。 我不认为你可以在ResetReferences(T data)
的实现中做任何通用的事情,T
没有通用的接口可以操作。
@zoujyjs:但实现不必是通用的——它可以特定于一种类型。这不是通用的方法 - 它是接口。所以有人可以实现IViewModel<Foo>
,他们只需要知道如何处理 Foo。【参考方案4】:
你需要实现接口方法,但你仍然可以做你想做的事
public class LocationViewModel : IViewModel
public void ResetReferences(List<StateProvinces> stateProvinces) // ...
void IViewModel.ResetReferences() // ...
【讨论】:
这不是一个好的解决方案,因为它违反了SOLID原则的接口隔离原则(ISP):一个类不得必须实现特定类不需要的任何接口元素!跨度> 【参考方案5】:接口的目的是让客户端代码知道接口并忽略实现。如果您的实现在调用时需要特殊处理,则客户端代码需要知道它正在调用什么实现,然后接口的整个目的就丢失了。
除非我完全误解了你想要完成的事情,否则你走错路了。
【讨论】:
是的,我认为你是对的。我把逻辑放在错误的地方。 (这是一个 MVC 应用程序,所以我现在将 ResetReferences 放在 Controller 类而不是 ViewModel 类中)。 完全正确。在实现类中隐藏功能会从interface
中带走很多价值,因为interface
并没有完全定义实现类将要做什么。以上是关于如何创建具有可变参数/不同方法签名的方法接口?的主要内容,如果未能解决你的问题,请参考以下文章
我可以将数组作为参数传递给 Java 中具有可变参数的方法吗?
使用 preg_replace_callback 查找并替换具有可变数量参数的函数签名