2011-11-27 45 views
2

我需要实现许多类的基本行为。举一个例子,假设它是一种绘图行为:可以绘制很多不同类型的对象,并且它们都需要一些属性和一些通用代码来实现绘图过程。假设我将这个通用部分放在一个名为Drawable的类中。C#中的基类可以像接口一样继承吗?

问题是这些不同的类可能会扩展其他类,所以我不能让它们从Drawable继承。显而易见的解决方案是使用接口(IDrawable),但后来我无法在其中实现任何代码;我可以想到的另一种解决方案是使用组合,通过创建一个DrawAction类来实现所有类的实例化,但这需要我在所有需要的类中放置相同的代码(如果只是几行)绘制。

有人可以给我关于如何做到这一点的建议吗?谢谢。

+2

听起来落得像你已经有了一个它很好的处理。你的问题具体是什么?是的,基类可以继承,就像接口一样(但是你只能从一个基类继承 - 在C#中没有多继承类)。如果你需要多重继承,你将不得不使用某种组合来获得它。 –

+0

我的问题具体是,我想避免在许多“派生”类中使用组合,我将要:-)请查看以下答案的评论以获得更详细的解释。 – Simone

回答

1

这听起来像装饰模式可能适合你想要实现的。

See Decorator Pattern Wikipedia entry

  • ,而不是试图继承常见的“绘图”的逻辑,将常见的逻辑在其他类即“画* ER *”
  • 当必须绘制的对象,它传递给适当的绘图* ER *(或进行抽奖* *吧)
  • 你仍然可以找到一个IDrawable接口非常有用,这样的抽奖* *可以针对已知接口编写代码。
  • 您可以用多个抽奖* *实现(在这种情况下,你将需要处理相应的抽屉的动态选择,无法得出每个对象)
+0

装饰模式可能会有所帮助。我会让装饰器包装一个对接口的引用,这样通用部分就被委托给装饰器,并且“custom”部分(依赖于“derived”类的部分)通过接口暴露出来,并由装饰。只要我回家,我会尽力实现这一点,我会尽快回复你。感谢您的输入! – Simone

4

这可能是composition的情况,而不是继承。

您可以在一个类中实现绘图行为,然后让所有需要它的类保持对它的引用。

如果您需要支持许多不同的绘图算法,您可能需要查看Strategy Pattern。在这里你可以实现许多不同的绘图算法,全部实现某种接口,需要绘制的对象可以参考其中的一个。

根据您的情况,如果某些类型的对象始终需要某种类型的绘图算法,那么使用IoC容器(如StructureMapUnity)可以自动选择哪个绘图类。

下面是DoFactory

+0

谢谢亚当!虽然我已经知道战略模式,但我并不了解StructureMap,也不了解Unity。从一眼看来,Unity似乎可以帮助我,但我想确保我们处于相同的波长。 下面是一个更详细的例子。通过使用合成,我会有类似于 '类Foo DrawAction m_oDrawAction = new DrawAction(); public override void Draw() { m_oDrawAction.Do(); } // Foo专属的其他东西 }' 我需要将它复制到我需要绘制的每个类中。有没有办法避免这种容易出错的代码重复? – Simone

5

您可以创建DrawAction类的实例,然后只用构造函数依赖注入,而不是明确每个类实例化它注射到其他类别的策略模式的一个例子,这个给你少再加设计以及:

IDrawAction drawAction = new DrawAction(); 
var drawable = new Drawable(drawAction); 

public class Drawable 
{ 
    public Drawable(IDrawAction drawAction) 
    { 
    } 
} 
+0

谢谢您的评论!我仍然需要编写使用'IDrawAction'对象的代码,并且此代码不能位于接口中。 另外,我不需要在不同的“派生”类中有不同的'IDrawAction'行为。从理论上讲,所有客户端类都从具体的基类继承是没有问题的,因为它们都需要做同样的事情(就绘图而言)。唯一的问题是,如果它们从非接口类型继承,那么它们不能从任何其他非接口类型继承,这是我无法忍受的限制。 – Simone

2

您可以IDrawable创建扩展方法:

public static class DrawableExtensions 
{ 
    public static int CalculateSize(this IDrawable drawable) 
    { 
     return drawable.Width * drawable.Height; 
    } 
} 

这样,这些apear了methodA是IDrawable接口上:

IDrawable d = new Circle(); 

int size = d.CalculateSize(); 

缺点是扩展方法是静态的,你不能覆盖它们。

+0

谢谢史蒂文!我不知道这个功能;感谢您谈论它。我害怕,但它不会帮助我,因为我的问题:-) – Simone

1

C#不支持多重继承。停止。你不能这样做。 您正在谈论“Mixins”...,它们在C#中仍然不受支持。

但是您可以使用多种选择。

更简单的是使用Mixin类,您可以将其添加为所有类中的字段。 例如...

public class DrawerMixin 
{ 
    public void DrawRectangle() { ... } 
} 

public class MyClass1 : Component 
{ 
    public DrawerMixin Drawer { get; private set; } 

    public MyClass1() 
    { 
     this.Drawer = new DrawerMixin(this); 
    } 

    public MyClass1(DrawerMixin drawer) 
    { 
     this.Drawer = drawer; 
    } 

    public void MyFunc() 
    { 
     ... 
     this.Drawer.DrawRectangle(); 
    } 
} 
+0

嗨萨尔瓦多,感谢您的评论!实际上,当我谈论使用合成时,这就是我想到的。正如我在另一个评论中所描述的,尽管如此,我希望摆脱在我的“派生”类中实例化mixin所需的代码重复。 在C/C++中,我会使用一个宏来实例化mixin。我仍然需要在每个“派生”类中包含宏,但我只需要编辑每个要更新的类的宏。至少有一种方法可以在C#中做这样的事情吗? – Simone