您没有提供太多详细信息,因此这里尝试从您提供的内容中进行回答。
看看基本的区别:
当你有一个基类型B
和一个派生类型D
时,这样的赋值:
B my_B_object = my_D_object;
分配对同一对象的引用。另一方面,当B
和D
是独立类型并且它们之间存在隐式转换时,上述赋值将创建一个副本并将其存储(如果是类my_D_object
,则为对它的引用) 。B
my_B_object
总之,“真正的”继承通过引用工作(对引用的更改会影响许多引用共享的对象),而自定义类型转换通常按值工作(这取决于您如何实现它,但实现类似于“通过引用”的东西“转换器的行为几乎是疯狂的):每个引用都将指向它自己的对象。
你说你不想使用接口,但为什么呢?使用组合接口 + 辅助类 + 扩展方法(需要 C# 3.0 和 .Net 3.5 或更高版本)可以非常接近真正的多重继承。看这个:
interface MyType { ... }
static class MyTypeHelper {
public static void MyMethod(this MyType value) {...}
}
为每个“基本”类型执行此操作将允许您为您想要的方法提供默认实现。
这些不会表现为开箱即用的虚拟方法;但您可以使用反射来实现这一点;您需要在 Helper 类的实现中执行以下操作:
- 检索
System.Type
一个value.GetType()
- 查找该类型是否具有与签名匹配的方法
- 如果你找到匹配的方法,调用它并返回(所以 Helper 的其余方法不会运行)。
- 最后,如果你没有找到具体的实现,让方法的其余部分作为“基类实现”运行和工作。
你去吧:C#中的多重继承,唯一需要注意的是在支持这一点的基类中需要一些丑陋的代码,以及由于反射而产生的一些开销;但除非您的应用程序在沉重的压力下工作,否则这应该可以解决问题。
那么,再一次,为什么你不想使用接口呢?如果唯一的原因是他们无法提供方法实现,那么上面的技巧可以解决它。如果您对接口有任何其他问题,我可能会尝试将它们整理出来,但我必须先了解它们;)
希望这可以帮助。
[编辑:根据评论添加]
我在原始问题中添加了很多细节。我不想使用接口,因为我想防止用户通过错误地实现它们,或者不小心调用一个方法(即 NewBar),如果他们想实现一个指标,他们需要重写该方法,但是他们永远不需要直接调用。
我已经查看了您更新的问题,但评论非常总结了它。也许我遗漏了一些东西,但是接口 + 扩展 + 反射可以解决多重继承可以解决的所有问题,并且比任务中的隐式转换要好得多:
- 虚拟方法行为(提供了一个实现,继承者可以重写):在帮助器上包含方法(包装在上面描述的反射“虚拟化”中),不要在接口上声明。
- 抽象方法行为(未提供实现,继承者必须实现):在接口上声明方法,不要将其包含在助手中。
- 非虚拟方法行为(提供了一个实现,继承者可以隐藏但不能覆盖):只需在助手上正常实现即可。
- 奖励:奇怪的方法(提供了一个实现,但继承者无论如何都必须实现;他们可能会显式调用基本实现):这对于普通或多重继承是不可行的,但为了完整性我将它包括在内:这就是你会得到的您在帮助程序上提供一个实现,并在接口上声明它。我不确定这将如何工作(在虚拟与非虚拟方面)或它有什么用途,但是嘿,我的解决方案已经击败了多重继承:P
注意:在非虚拟方法的情况下,您需要将接口类型设置为“已声明”类型,以确保使用基本实现。这与继承者隐藏方法时完全相同。
我想通过错误地实现它们来防止用户在脚上开枪
似乎非虚拟(仅在助手上实现)在这里效果最好。
或意外调用一个方法(即 NewBar),如果他们想要实现一个指标,他们需要重写该方法
这就是抽象方法(或接口,一种超级抽象的东西)最闪耀的地方。继承者必须实现该方法,否则代码甚至无法编译。在某些情况下,虚拟方法可能会起作用(如果您有通用的基本实现,但更具体的实现是合理的)。
但他们永远不需要直接调用
如果一个方法(或任何其他成员)暴露给客户端代码但不应从客户端代码调用,则没有编程解决方案来强制执行该方法(实际上,有,请耐心等待)。在文档中解决该问题的正确位置。因为您正在记录您的 API,不是吗?;) 转换和多重继承都不能帮助你。但是,反思可能会有所帮助:
if(System.Reflection.Assembly.GetCallingAssembly()!=System.Reflection.Assembly.GetExecutingAssembly())
throw new Exception("Don't call me. Don't call me!. DON'T CALL ME!!!");
当然,如果您using System.Reflection;
的文件中有声明,您可以缩短它。而且,顺便说一句,请随意将异常的类型和消息更改为更具描述性的内容;)。