如何避免冗余的接口实现

本文关键字:接口 实现 冗余 何避免 | 更新日期: 2023-09-27 17:53:58

我有一个设计问题。我将提出一个假设的情况。我的应用程序需要几个接口才能使对象可用。假设它们是;

1.  IAdult.cs, with two properties
  a.    Age
  b.    LicenceNo.
2.  IEducated.cs, with two methods
  a.    Read()
  b.    Write()

让我们假设这些接口的实现在大多数情况下保持相同。因此,如果我们必须从这些接口中实现一个抽象类,我们可以简单地创建一个类,例如,抽象类EducatedAdult{}。现在我们定义三个不同的类,它们各自有各自的继承和一组各自的属性;

1.  Carpenter.cs (derives from class A)
2.  Plumber.cs (derives from class B)
3.  Programmer.cs (derives from class C)

这里,类A, B, C是一些我无法编辑的外部库的一部分。现在要使这些对象在程序中可用,它们需要实现上述给定的接口。所以问题是,对于这些类中的每一个,我都必须显式地实现上述接口。有没有更好的设计,我不必在所有类中冗余地实现接口。如果可能的话,这可能是一个解决方案;

EducatedAdult<t>: t, IAdult, IEducated { <implementation of interfaces> }之后,我可以初始化派生类,比如;

Carpenter carpenter = new EducatedAdult<Carpenter>()。这并不是一个理想的解决方案,因为carpenter对象的公共接口仍然不包括我的接口成员(不需要强制转换)。那么,什么才是最合适的设计呢?

如何避免冗余的接口实现

你不能在。net中为接口提供默认的实现,它只是由实现类来提供实现,但是你可以在接口上使用扩展方法来实现它。

在你的例子中,你应该创建一个类,为你的三个类实现所有的通用方法,在EducatedAdult实现抽象,然后在每个类上实现特定的方法。

见到你

好了,既然你更新了你的问题:

  • 使用某种mixin方法,如下所述:http://www.codeproject.com/KB/cs/C__3_Mixin.aspx
  • 使用像DynamicProxy这样的工具来做真正的混合:http://devlicio.us/blogs/krzysztof_kozmic/archive/2009/08/12/castle-dynamic-proxy-tutorial-part-xiii-mix-in-this-mix-in-that.aspx

Update:工作量最少的方法可能是:

public interface IAdult { }
public interface IEducated { }
public static class Extensions
{
    // IAdult extensions
    public static void Age(this IAdult adult)
    {
        ...
    }
    public static void LicenseNo(this IAdult adult)
    {
        ...
    }
    // IEducated extensions
    public static void Read(this IEducated educated)
    {
        ...
    }
    public static void Write(this IEducated educated)
    {
        ...
    }
}

然后用空接口标记你的类,这样你就没有什么要实现的

public class Carpenter : IAdult, IEducated
{
}

你可以这样使用:

var carpenter = new Carpenter();
carpenter.Read();

如果你想"覆盖"接口方法以提供不同的实现,你可以这样做:

public class Carpenter : IAdult, IEducated
{
    public void Read() { ... }
}

当你现在在Carpenter对象上调用Read()时,它将使用来自Carpenter类的实际Read()方法而不是扩展方法。您甚至可以将其设置为virtual,并从Carpenter派生,并像以前一样在子类中重写它。为了在Carpenter对象中调用Read()的默认实现,您必须执行Extensions.Read(this)而不是base.Read()

不幸的是,如果没有某种汇编重写器或不使用dynamic,您无法在c#中做到这一点。你可以做一些类似mixin的事情,但是这会改变你的设计。

如果你可以使用另一种语言,Oxygene和Nemerle提供了一个功能,通过将其所有成员委托给一些也实现接口的字段来实现接口。