【问题标题】:How To Get around multiple inheritance如何绕过多重继承
【发布时间】:2013-01-17 22:58:57
【问题描述】:

我正在尝试在 C# 中实现以下内容,以便我可以强制初始化父类中的某些事件委托和变量,或者我会改用接口。显然下面的语法不正确。

具体的类是 Class1 & class 2。

这里的想法 MyClass 是一个按钮,它是一个图像,它是别的东西。

编辑: " 我明白 selectable 和其他不是对象而是状态。我真正想做的是编写代码以适当的方法维护可选择的状态,因为它将是对所有这些都相同。即在单击事件(单击位置)上,根据我的边界框检查我是否被单击,将状态更新为选中。我在 XNA 中,这是 ac# 轮询环境,我正在尝试制作尽可能将 GUI 作为事件驱动,如果这有意义吗?”

 public abstract class Class1
    {
        private int NumberNeededForMethod;

        private void methodThatOccursWhenEventHappens(int NumberNeededForMethod)
        {
            // stuff using NumberNeededForMethod;
        }

        private Class1(int NumberNeededForMethod)
        {
            MethodDelegate += methodThatOccursWhenEventHappens(int
            NumberNeededForMethod)
            ;
        }
    }


public abstract class Class2
    {
        private int NumberNeededForMethod2;

        private void methodThatOccursWhenEventHappens2(int NumberNeededForMethod2)
        {
            // stuff using NumberNeededForMethod2;
        }

        Class2(int NumberNeededForMethod2)
        {
            MethodDelegate += methodThatOccursWhenEventHappens(int NumberNeededForMethod2);
        }
    }

public class ClassThatIsBothClass1andClass2: Class1, Class2
{
    ClassThatIsBothClass1andClass2( int NumberNeededForMethod1, int NumberNeededForMethod2) : Class1(NumberNeededForMethod1),Class2(NumberNeededForMethod2)
    {

    }
}

【问题讨论】:

  • 通常的方法是使用组合而不是继承。 (例如,ClassThatIsBothClass1andClass2 将继承自 Class1contain Class2。)
  • 并使用接口。例如。有 IBooth : IFirst, ISecond。然后有一个类 Both 实现 IBoth 并在其中有两个类型为 First 和 Second 的对象,它将方法调用和/或属性值转发到。
  • (感谢大家的回复)我正在学习并努力做到这一点。 svick,请参阅下面我对构图的想法,并请回复,我只是想在以后解决这个问题。还有亚历克斯,我希望能够轻松地将这些东西组合在不同的地方,我有两个以上,所以我最终会为类的每个组合制作大量的接口包装器。
  • 但是您不必编写大量 ifc 包装器,您可以(并且应该)仅出于特定目的引用该对象,例如您应该编写您的方法,以便它们引用最小公分母,例如DoSomethingToIFirst(IFirst first)。然后,如果您有一个可选择的,它实现ISelectable(除其他外),您可以并且应该仅在其他地方引用它。如果你用这种方式编码,你很少需要ISelectableFocusableMovableImage

标签: c# inheritance interface abstract-class multiple-inheritance


【解决方案1】:

首先,当然,C#支持多重继承,所以无论你实现什么多态性都必须使用接口和组合来完成。

参考this comment可拖动可选择可拥有 em> 是对象的属性

ImageButton 对象。

按钮不能拥有。

但按钮可以拥有、可拖动或可选择。我想知道的是,这些属性是否不仅仅是单个 IAshtonControl 接口上的属性?

可以想象,一个按钮也可以是一个图像。这很有道理。

由于 C# 缺少多重继承,您根本无法创建派生自 ButtonImage 基类的 AshtonButton 类。

可以做的一件事是创建一个实现IAshtonControl 接口的AshtonButton 类,并且该接口的实现可以委托给一个工作类的私有实例,该实例可以执行任何工作对所有 IAshtonControl 实例通用。

或者,如果需要,您可以使用单独的 IOwnableIDraggableISelectable 接口。

无论哪种方式,都可以如实声明AshtonButtonIAshtonControl,可拥有、可拖动、可选择。对于不同的控件,这些东西可能具有不同的含义(不同的行为/视觉效果),或者它们可能没有,但是您可以将这些实现细节隐藏在接口后面,以便您可以以编程方式以相同的方式处理每个对象,而不管其实现如何.

将对象与其属性分开很重要,因为这会影响您思考问题的方式。 可拖动不是一个东西,它是一个东西的特性。

但是,如果您的目标是拥有一个 Button 也是一个 Image,那么某种类型的组合或委托是实现该目标的方法。如果您有一个IAshtonImage 接口,那么您将在AshtonImage 类和AshtonImageButton 类上实现它。然后你有一个AshtonImage 类的内部实例(组合),在AshtonImageButton 类中,并将对IAshtonImage 成员的调用委托给私有(组合)AshtonImage 实例,依此类推。

【讨论】:

  • 感谢您的回复。我知道 selectable 和 others 不是对象而是状态。我真正想做的是以适当的方法编写保持可选状态的代码,因为它们对所有人都是一样的。即在单击事件(单击位置)上,根据我的边界框检查我是否被单击,将状态更新为选中状态。我在 XNA 中,这是一个 c# 轮询环境,我正在尝试使 GUI 尽可能地成为事件驱动的,如果这有意义吗?
  • 我可能会提炼出对每种情况(Button、Image、FlyingSquirrell)绝对通用的事件处理程序和状态更改程序集,并将它们放在一个完全通用的 AshtonControl 基类中。所有其他控件都将派生自该公共基类。然后我会在此基础上将其他概念分层,以解释更具体控件的差异。您仍然可以使用接口和组合,例如,创建一个 Button、一个 Image 和一个 ImageButton。
  • 我会小心过多的继承。有 7 层继承是可怕的。一个更好的解决方案是有一个“ISelectController”,它有一个方法“ShouldSelect(ISelectable selectable, IHost host)”并确定它是否应该选择。然后,您可以在所有“ISelectable”控件中保留它的一个实例。请注意关键是如何拥有清晰的合同 - 接口。一个控件可以实现很多,并且只应被客户端代码引用以实现其实现的目的,并被最窄的 ifc 用于此目的。
  • 我想我只是在谈论 3 个级别,并加入了一些构图... Control -> Button -> ImageButton(contains Image)。 :-) 但我完全同意您的评论,需要注意的是,如果图像和按钮需要执行不同的操作以响应单击事件,那么基类实现可能会很有用。另一方面,很可能 ImageButton 需要以自己独特的方式来进行点击,与单独的图像或按钮不完全相同,并且基类可能真的会阻碍...... .
  • ...如果 ImageButton 点击​​的行为需要独特,而不是常规的 Button 或 Image 点击,那么界面看起来非常干净。只需在您的接口中定义您的事件处理程序,并为真正通用的部分使用推荐的工作类,如@h.alex。深层的类层次结构与关注点分离的概念作斗争。在某些时候,很难真正记住祖先类的所有行为和副作用,或者检查这件事。
【解决方案2】:

您可以使用组合来创建一个包装 class1 和 class2 的类,并且是响应您的按钮引发的事件的东西。

【讨论】:

  • 从概念上讲这有点奇怪。我计划调用诸如 Draggable、Selectable、Ownable、Image、Button 之类的类。因此,我可以在需要时混合和匹配最终的屏幕对象。如果我创建一个具有可拖动实例的类,那就有点奇怪了。
  • 我不完全确定你想要实现什么(我只看到了你的代码的一小部分)如果它有帮助,我倾向于沿着向类添加行为的思路(特别是 winforms 中的 UI 类)以使它们的行为不同。您的行为可以封装在一个类中,并添加到您想要表现不同的类中。这只是一种组合形式,这意味着您不必按照您建议的方式为类编写一大堆包装器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-16
  • 2016-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-27
相关资源
最近更新 更多