将*接口*或*对象*作为参数传递给函数更好吗?
我试图说服一位同事,函数应该采用接口作为参数,而不是对象本身。 我认为小对象可以很好地传递,但对于大对象,我会给它们一个接口,只传递 i/f,而不是整个对象。
请注意,这些大类中只会有一个 - i/f 永远不会用于不同的对象。 这仅仅是为了隐藏对象的实现。
您是否同意将一个大类分成一个或多个接口是一种好的做法?
这样做有什么缺点吗?
例子:
public interface class IVeryLargeClass
{
void DoSomething();
...
};
public ref class VeryLargeClass : public IVeryLargeClass
{
public:
virtual void DoSomething() { ... }
...
};
public ref class AnotherClass
{
public:
AnotherClass(VeryLargeClass^ vlc) { vlc->DoSomething(); }
// OR
AnotherClass(IVeryLargeClass^ vlc) { vlc->DoSomething(); }
};
I'm trying to convince a colleague that a function should take an interface as a parameter, and not the object itself. I think small objects can be fine to pass across, but for large ones I would give them an interface and just pass the i/f over, not the whole thing.
Note that there will only ever be one of these large classes - the i/f will never be used for a different object. This is merely for hiding the implementation of an object.
Would you agree that separating a large class into an interface(s) is good practice?
Are there any disadvantages to doing this?
Example:
public interface class IVeryLargeClass
{
void DoSomething();
...
};
public ref class VeryLargeClass : public IVeryLargeClass
{
public:
virtual void DoSomething() { ... }
...
};
public ref class AnotherClass
{
public:
AnotherClass(VeryLargeClass^ vlc) { vlc->DoSomething(); }
// OR
AnotherClass(IVeryLargeClass^ vlc) { vlc->DoSomething(); }
};
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在 OO 开发中您学到的首要原则之一:
您指出“永远只有这些大类之一 - i/f 永远不会用于不同的对象”。 对于你的情况来说,这可能是正确的,但我希望每次这样的陈述被证明是错误的,我都能得到五分钱。
除了考虑您的接口是否可能有多个实现之外,您还应该考虑您的具体对象是否导出(或可能导出)与接口中声明的操作不共享逻辑关联的其他方法。 在这种情况下,您可以简单地在一个或多个附加接口中声明附加操作。 那么,客户端只需要与导出其感兴趣的操作的接口相结合。
简而言之,接口提供了一种管理客户端和提供者之间耦合的方法。
One of the first principles you learn in OO development:
You indicate that "there will only ever be one of these large classes - the i/f will never be used for a different object". This might be true in your case, but I wish I had a nickel for every time such a statement turned out to be wrong.
In addition to considering whether there might be multiple implementations of your interface, you should also consider whether your concrete object exports (or might export) additional methods that do not share a logical affinity with the operations declared in the interface. In such a case, you could simply declare the additional operations in one or more additional interfaces. A client, then, need only couple with the interface that exports the operations in which it is interested.
Put simply, interfaces provide a means of managing the coupling between clients and providers.
依赖倒置原则可以总结为:依赖抽象更好比结核。
传递接口几乎总是比传递具体类更好。
也就是说,在特定模块中,针对内部类型的高内聚性是可以的,但是对于何时以及如何传递具体对象是非常主观的。
The Dependency Inversion Principle can be summed up as: It is better to depend on abstractions than concretions.
It's almost always better to pass an interface than it is to pass a concrete class.
That said, high cohesiveness against internal types is ok within a particular module, but that's very subjective as to when and how you should pass concrete objects.
我宁愿避免为了创建接口而创建接口。 如果您可以在多个地方使用该接口,那么您就获胜了 - 或者如果这是一个公共函数和类并且您特别想要简化。
I'd prefer to avoid creating and interface for the sake of creating an interface. If you can use that interface in more than one place, then you have a winner - or if this is a public function and class and you specifically want to simplify.
如果您传递了一个实现,您就失去了使用接口的优点之一,这意味着将逻辑与实际实现分开。
http://en.wikipedia.org/wiki/Interface_(computer_science)
If you pass an implementation, you kind of loose one of the advantages of using interfaces, meaning separating the logic from the actual implementation.
http://en.wikipedia.org/wiki/Interface_(computer_science)
另一个问题是你的班级本身非常大。 这可能不在您正在做的事情的范围内,但是一个非常大的类意味着它可能首先做了太多的事情。 您能否将其重构为更小的类,其中您所调用的函数中所需的信息封装在其自己的更小的类中? 如果您针对该类创建一个接口,您可能会发现它比您当前拥有的非常大的类更具可重用性。
The other issue is your very large class itself. This may not be within the scope of what you're doing, but a very large class implies that it might be doing too much in the first place. Can you refactor it into smaller classess, where the information required within the function you're calling is encapsulated in its own smaller class? If you create an interface against that class you may find it that much more re-usable than against the very large class you currently have.