【问题标题】:Multiple Inheritance is not supported in C# so how can I get this to work?C# 不支持多重继承,那么我怎样才能让它工作呢?
【发布时间】:2017-09-18 22:19:42
【问题描述】:

我创建了两个具有不同用途的 DataGridView,我想将它们组合在一起。我之前没有意识到你不能从多个基类继承。

我查看了其他各种 Stack Overflow 问题,发现人们推荐界面或组合解决方案的共同主题。我尝试将这些概念应用到我的情况中,但它们似乎不太适合。

首先,这是我希望的结构...


RowSelectionDataGridView - 选择整行的 DataGridView 并具有用于轻松设置颜色等样式的选项

DragAndDropDataGridView - RowSelectionDataGridView,允许用户单击行以拖动到另一行的顶部并将行移动到它们被放置的位置

ContextMenuDataGridView - RowSelectionDataGridView 显示右键单击行上方的 ContextMenuStrip,用于复制、粘贴、删除等操作

CombinedDataGridView(不是实际名称)= DragAndDropDataGridView 和 ContextMenuDataGridView 可以让用户拖放并且在右键单击时还有一个上下文菜单条

                                        DataGridView                          
                                             ▲                                
                                             |                                
                                             |                                
                                  RowSelectionDatatGridView                   
                                             ▲                                
                                             |                                                                
                        _____________________|_____________________           
                       |                                           |          
                       |                                           |          
             DragAndDropDataGridView                   ContextMenuDataGridView
                       ▲                                           ▲          
                       |                                           |          
                       |___________________________________________|          
                                             |                                
                                             |                                
                                             |                                
                                    CombinedDataGridView                      

如果我要实现...

接口: 我的理解是 ContextMenuDataGridView 和 DragAndDropDataGridView 需要成为接口,然后 CombinedDataGridView 将从这两者继承。我不明白这一点,因为无论如何,所有逻辑都必须在 CombinedDataGridView 中实现。这样做的主要好处是什么?或者我对此有什么误解?

组合: 我的理解是,CombinedDataGridView 中会有 DragAndDropDataGridView 和 ContextMenuDataGridView 的实例。这似乎没有任何意义。

我需要如何构建我的类以获得我想要的功能?

【问题讨论】:

  • 我想将它们组合在一起。嗯,是的,但是是什么让您认为 MI 会是一种很好且有用的方法呢??
  • @TaW 我以为一旦创建了不同的 DataGridViews 就会很容易,但是当我尝试public class CombinedDataGridView : DragAndDropDataGridView, ContextMenuDataGridView 时却收到错误消息,这让我感到非常惊讶。在看到那个错误之后,为什么我不能这样做是有道理的,但我不确定替代方法是什么。我认为您可以轻松地从共享相同基类的两个基类中派生出来,并且它可以获得两组功能。
  • 第一步:摆脱 ooop(overdone oop)的想法,认为一切都已定义为它本来的样子。相反,大多数是由它可以做什么来定义的。哪些是你给一个好名字和分组的方法,是的,接口。而且,是的,它们必须在每个参与类中实现。这不是那么乏味,而是每次都有机会正确地做到这一点..

标签: c# inheritance interface multiple-inheritance composition


【解决方案1】:

我在一次采访中被问到这个问题。 您可以使用设计模式。 Design pattern to use instead of multiple inheritance

【讨论】:

  • 这似乎可以工作,但我很难从这些问题的接受答案转换为我的情况。我的哪个类应该是接口?
  • 两者都不是。接口包含(声明)特性,而不是类的任何其他部分,如字段等。
  • 那么我的界面会有哪些功能呢?对不起,我不是偷懒,我只是真的不明白。我整天都在玩弄这个问题。我以前从未实现过接口。
  • 好吧,不用深入探讨挂钩事件的编码细节,您选择的名称是一个好的开始:IRowDragable 和 IContextMenueEnabled 有点长,但切中要害..
  • @TaW 我想我可能终于明白了!你的接口名称在我脑海中激起了一些东西。因此,这些接口实际上并不是从 DataGridView 继承的,而是表明任何继承 IRowDragable 的对象都需要实现这些东西。而且 IRowDragable 甚至根本没有绑定到 DataGridView。这是对的吗?
【解决方案2】:

您可以通过从“is-a”转变为“has-a”来实现您想要的。与其创建不同类型的行为不同的类,不如创建一个可以接受列表中不同行为的类。然后使用这些行为来使其余功能正常工作。 (你的类行为而不是一个只表示一种行为的东西)。

如果我能看到你的代码,我只能提供更多细节。在所有各种设计模式中,您应该找到一些可以让您更清楚地了解如何实现您想要的东西。一种开始的模式是装饰器。还有其他可能有用的。

【讨论】:

    【解决方案3】:

    TL;DR:Honey don't


    1.多重继承 (MI)

    继承基于 'A' 的概念 是一个 'B',但有一些添加或更改。

    这很有意义。

    然而,MI 将这个想法扩展到'A' is both a 'B' and a 'C' 在概念上遇到了许多问题,尤其是。当两个“父母”要么太不同(例如:“车辆”和“食物”)或太相似时。后者可能引入问题的一个原因是“冲突”,即领域(或方法) 父母双方都有..;现在,将在 'A': 'B.field1''C.field1' 中使用?如果不总是排位赛,这会变得相当混乱。

    当 A. Hejlsberg 开始设计 C# 时,他不仅设计了从 PascalTurbo Pascal 的扩展,还设计了非常成功的 Delphi em> 框架。他还实现了 Microsoft 的 Java 编译器。所以他知道 MI 会带来的问题,并决定 MI 真正提供的好处(多态性和可重用性)都可以通过 Interfaces..

    来实现

    2。接口

    Interface 不是对象,也不包含任何代码或任何数据。这是一个契约,它承诺任何带有这个Interface 的类都将提供一组特定的功能。

    理解和欣赏这个概念的最好方法是研究.Net 框架。看看IComparable。只要它们是IComparable(而且,我认为IEnumerable),它就是以自己特殊的方式对所有类型的事物进行排序的基础;然而,所有这些类型都可以依赖于特定的比较方法。这允许您实现通用功能一次并一次又一次地重用 .

    一个常用的例子是关于形状的。使用继承来构建一个包含圆形、三角形、矩形、正方形的继承链或树会导致各种冲突。但是添加IDrawable 接口是很自然的,例如,您可以将它们收集到@ 987654340@ 然后您可以枚举它..

    另一个例子是ISerializable,它还提供(或者更确切地说是承诺)以特殊方式实现的通用服务。

    3.您的情况

    很抱歉,您的情况最好通过放弃整个想法来“解决”。

    这不仅是有问题的,因为父母双方都是视觉控件,这使得 MI 冲突特别容易发生。实际上两者都是完全相同的,即都是DataWindows!这是一场 MI 噩梦,因为每个领域都会发生冲突!

    4.如何解决它

    • 最自然的方法是放弃整个 MI 方法,并像框架本身那样做:在继承链中引入有意义的特性。除了该功能,我们还引入了 'bool CanDoOrHasFeature' 属性,一切都很好。

    最明显的例子是所有'AllowUserToXYZ' 属性DataGridView 具有..

    不要担心这会使程序臃肿:类定义只加载一次! (当然,如果你想提供逻辑,代码必须编写/加载一次。)

    • 另一个选项是辅助类;您可以编写一个ReorderElements 类并让那些控件注册到您想要提供此功能的那些。我有一个ControlMover 类,并让我想要移动的控件订阅它的服务..

    【讨论】:

    • 您对避免多重继承的解释假设非虚拟 MI。虚拟 MI 避免了您描述的大部分缺点(但可能会添加一些自己的缺点)。当然,C# 也不支持,您建议的替代方案是避免此处需要 MI 的好方法。
    • @TaW 实际上,我最初所做的事情与您的解决方案非常相似。我希望有一种方法可以分离功能,这里的一些答案给出了看起来很有希望的方法。不幸的是,它们最终并没有真​​正对我的情况有效,实际上只是添加了额外的代码。
    猜你喜欢
    • 2017-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-25
    • 2022-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多