4

所以,我想听听大家对此的看法。

我有一个项目,其中三个不同的继承路径都需要实现另一个基类。这将是多重继承,并且在 C# 中是不允许的。我很好奇如何在不重复代码的情况下实现这一点。

编辑:我不拥有这三个班级。这三个类来自 3rd 方代码。所以我不能让它们都扩展我的基类。

现在我正在使用三个不同的类,每个类都扩展了一个不同的基类。然后我在三个抽象类中的每一个中都有相同的代码。

我可以使用单个界面,但我仍然需要复制代码。

我可以制作某种实现代码的静态类,然后在 3 个抽象类中的每一个中引用它。它会消除重复,但是,我不确定我对此有何感受。我可以在接口上实现扩展方法,但是接口本身会是空的,并且扩展方法(包含重复的代码)会在一个完全不同的文件中,这似乎不太正确。另外我不能在扩展方法中实现属性......

我怎样才能排除这里的代码重复?

编辑,继承树:

class Class1 : 3rdPartyBaseClass1 { }
class Class2 : 3rdPartyBaseClass2 { }
class Class3 : 3rdPartyBaseClass3 { }

我有我想在上述每个类中的代码,但我不能将它添加到 3rdPartyClasses。

4

5 回答 5

6

创建 Class1、Class2 和 Class3 可以实现的接口。然后将您的代码放入扩展方法中,使其适用于所有人。

interface IMyInterface {
    void Foo();   //these are the methods that these 
        //classes actually have in common
    void Bar();    
}

public class Class1 : 3rdPartyBaseClass1, IMyInterface {
    // whatever

}

public static class IMyInterfaceExtensions {
    public static void CommonMethod(this IMyInterface obj) {
        obj.Foo();
        obj.Bar();
    }
}

public static class Program {
    public static void Main() {
        var instance = new Class1();
        instance.CommonMethod();
    }
}
于 2009-09-27T02:44:20.420 回答
5

好的,你可以做一些类似于我之前的建议的事情,也类似于递归的建议。对于您在所有三个派生类中所需的功能,您可以创建一个接口以及一个实现该接口的类(称为“实施器”)(并且具有您希望在每次调用时执行的实际代码) )。

然后,在每个派生类中,实现接口创建实现器的私有实例。在每个接口方法中,您只需将调用传递给 Implementer 的私有实例。因为 Implementer 和您的派生类都实现了您的 Interface,所以您对 Interface 所做的任何更改都需要您相应地修改 Implementer 和派生类。

并且您的所有代码都在一个地方,除了将调用传递给 Implementer 的私有实例的所有行(显然多重继承会比这更好,但是您与您拥有的军队而不是您希望的军队开战你有过)。

更新:向每个派生类添加一个类的公共实例怎么样?

public class DerivedClass1 : ThirdPartyClass1
{
    public MyClass myClass = new MyClass();
}

或者,如果您关心 Demeter 是谁并且您从 LOC 获得报酬:

public class DerivedClass1 : ThirdPartyClass1
{
    private MyClass _myClass = new MyClass();
    public MyClass myClass
    {
        get
        {
            return _myClass;
        }
    }
}

然后你只需像这样调用 MyClass 方法:

DerivedClass1 dc1 = new DerivedClass1();
dc1.myClass.DoSomething();

这样,我们都可以睡觉了。

于 2009-09-27T03:24:55.610 回答
4

与MusiGenesis 的建议类似,如果您需要3rd 方类的功能但又不必继承它们,则可以使用组合如下:

class ThirdPartyBaseClass1
{
    public void DoOne() {}
}

class ThirdPartyBaseClass2
{
    public void DoTwo() { }
}

class ThirdPartyBaseClass3
{
    public void DoThree() { }
}

abstract class Base
{
    public void DoAll() { }
}

class Class1 : Base
{
    public void DoOne() { _doer.DoOne(); }
    private readonly ThirdPartyBaseClass1 _doer = new ThirdPartyBaseClass1();
}

class Class2 : Base
{
    public void DoTwo() { _doer.DoTwo(); }
    private readonly ThirdPartyBaseClass2 _doer = new ThirdPartyBaseClass2();
}

class Class3 : Base
{
    public void DoThree() { _doer.DoThree(); }
    private readonly ThirdPartyBaseClass3 _doer = new ThirdPartyBaseClass3();
}

这也使您可以自由定义您想要的任何接口并在您的类上实现它们。

于 2009-09-27T03:53:00.270 回答
1

听起来您需要在这三个路径组合在一起的任何时候将新的抽象类插入到继承树中,但实际上没有足够的信息可以说明。如果您可以发布一些继承树,那将有很大帮助。

于 2009-09-27T02:30:19.747 回答
1

我认为您可能想使用组合而不是继承。具体怎么做取决于第三方类是什么样的,以及你自己的代码是什么样的。一些与您的问题相关的更具体的代码会有所帮助,但例如,假设您想要三个不同的第三方 GUI 小部件,所有这些小部件都需要使用您自己的初始化程序代码进行自定义。

案例 1:假设您的第三方小部件如下所示:

public interface IThirdPartyWidget {
  public void doWidgetStuff();
}

public class ThirdPartyWidget1: ThirdyPartyWidget implements IThirdPartyWidget {
 ...
}

public class ThirdPartyWidget2: ThirdPartyWidget implements IThirdPartyWidget {
 ...
}

你可以做:

public class MyWidget implements IThirdPartyWidget {
 private IThirdPartyWidget delegateWidget;
 public MyWidget(IThirdPartyWidget delegateWidget) {
  this.delegateWidget = delegateWidget;
 }

 public void doWidgetStuff() {
  delegateWidget.doWidgetStuff();
 }
}

案例 2:假设您绝对需要扩展这些小部件,并且您必须重构自己的代码:

public class MyWidget1: ThirdPartyWidget1 {
 public void myMethod() {
  runMyCode();
 }

 private void runMyCode() {
  //something complicated happens
 }
}

public class MyWidget2: ThirdPartyWidget2 {
 public void myMethod() {
  runMyCode();
 }

 private void runMyCode() {
  //something complicated happens
 }
}

这可以变成:

public class MyCodeRunner {
 public void runMyCode() {
  //...
 }
}

public class MyWidget1: ThirdPartyWidget1 {
 private MyCodeRunner myCode = new MyCodeRunner();
 public void myMethod() {
  myCode .runMyCode();
 }
}

public class MyWidget2: ThirdPartyWidget2 {
 private MyCodeRunner myCode = new MyCodeRunner();
 public void myMethod() {
  myCode .runMyCode();
 }
}

希望这是有道理的!

于 2009-09-27T04:13:06.877 回答