所以,我想听听你们对此的看法。
我有一个项目,其中三个不同的继承路径需要全部实现另一个基类。这将是多重继承,在C#中是不允许的。我很好奇如何在没有代码重复的情况下实现这一点。
编辑:我不拥有这三个班级。这三个类来自第三方代码。所以我不能让它们都扩展我的基类。现在我正在使用三个不同的类,每个类扩展一个不同的基类。然后我在三个抽象类中都有相同的代码。
我可以使用单个界面,但我仍然需要复制代码。
我可以创建一些实现代码的静态类,然后在3个抽象类的每一个中引用它。它会消除重复,但是,我不确定我对此的看法。我可以在接口上实现Extensions方法,但接口本身将是空的,扩展方法(包含重复的代码)将在一个完全不同的文件中,这似乎不太正确。另外,我无法在扩展方法中实现属性...
如何在此处分解代码重复?
编辑,继承树:
class Class1 : 3rdPartyBaseClass1 { }
class Class2 : 3rdPartyBaseClass2 { }
class Class3 : 3rdPartyBaseClass3 { }
我想要在上面的每个类中使用代码,但我无法将其添加到3rdPartyClasses。
答案 0 :(得分: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();
}
}
答案 1 :(得分:5)
好的,你可以做一些类似于我之前的建议,也类似于递归的建议。对于所有三个派生类所需的功能,您可以创建一个单独的接口以及一个实现该接口的类(称为“实施者”,用于踢脚)(并且具有您希望在每次调用时执行的实际代码) )。
然后,在每个派生类中,实现Interface 和创建Implementer的私有实例。在每个接口方法中,您只需将调用传递给Implementer的私有实例。由于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();
这样,我们都可以睡觉了。
答案 2 :(得分:4)
类似于MusiGenesis的建议,如果你需要第三方课程的功能,但 没有从他们那里下来,你可以使用组成如下:
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();
}
这也使您可以自由定义所需的任何接口并在类上实现它们。
答案 3 :(得分:1)
听起来你需要将新的抽象类插入到继承树中,无论这三条路径聚集在一起,但实际上还没有足够的信息可以告诉你。如果您可以发布一些继承树,那将会有很大帮助。
答案 4 :(得分: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();
}
}
希望这是有道理的!