【发布时间】:2013-04-16 11:30:49
【问题描述】:
我非常喜欢这个提示:“针对接口编程,而不是针对实现编程”,并且我一直在努力遵循它。然而,当我必须将我的代码与 必须 从多个接口继承的对象中分离时,我怀疑如何保持这一原则有效。一个典型的例子可能是:
namespace ProgramAgainstInterfaces
{
interface IMean
{
void foo();
}
class Meaning : IMean , IDisposable
{
public void Dispose()
{
Console .WriteLine("Disposing..." );
}
public void foo()
{
Console .WriteLine("Doing something..." );
}
}
class DoingSomething
{
static void Main( string[] args)
{
IMean ThisMeaning = (IMean ) new Meaning (); // Here the issue: I am losing the IDisposable methods
ThisMeaning.foo();
ThisMeaning.Dispose(); // Error: i cannot call this method losing functionality
}
}
}
解决此问题的一种可能方法是定义一个继承自两个接口的 ad-hoc 接口:
namespace ProgramAgainstInterfaces
{
interface IMean
{
void foo();
}
interface ITry : IMean , IDisposable
{
}
class Meaning : ITry
{
public void Dispose()
{
Console .WriteLine("Disposing..." );
}
public void foo()
{
Console .WriteLine("Doing something..." );
}
}
class DoingSomething
{
static void Main( string[] args)
{
ITry ThisMeaning = (ITry ) new Meaning (); // This works
ThisMeaning.foo();
ThisMeaning.Dispose(); // The method is available
}
}
}
但我不确定这是否是更紧凑和更有效的解决方案:我可以拥有更复杂的多重继承层次结构,这会增加复杂性,因为我必须创建接口仅用作容器。有更好的设计方案吗?
【问题讨论】:
-
这可能是一个有趣的问题,可以在programmers.stackexchange.com 提出。
-
通常你会检查接口的实现——例如
var disposable = ThisMeaning as IDisposable; if(disposable != null) disposable.Dispose()- 这意味着您在运行时发现实现,而不是在编译时了解它们 -
@Charleh:回答一下
-
@Thilo 完成!我更喜欢这种方法,因为这意味着您可以通过支持越来越多的接口来附加地构建类型 - 显然,请留意任何警告,但在类设计阶段,您应该知道无论如何应该支持接口明智
-
我不喜欢进行运行时检查以查看您的对象是否实际上实现了除了您知道它实现的接口之外的其他接口。为什么会呢?我会说您正在使用具体类(含义)的隐性知识来影响您的代码,我认为这破坏了对接口进行编程的整个要点。使用类型系统使您的假设明确。如果您需要一次性类型,您应该针对扩展 IDisposable 的接口编写代码,或者直接针对具体类型编写代码。