在.NET中多重inheritance有什么好的select?
我在WPF应用程序中遇到了一些与我的类层次结构有关的问题。 这是两个inheritance树合并在一起的问题之一,并且没有任何合理的方法来使inheritance在没有多重inheritance的情况下顺利进行 。 我想知道是否有人有任何明智的想法,让这种系统工作,没有使其无法遵循或debugging。
我是一个低级别的工程师,所以我的第一个想法总是这样:“哦,我会用C ++编写一些这样的类,然后在外部引用它们,然后我可以让所有的老派OO都变得有趣! 唉,当你需要从托pipe控件inheritance时,这没有帮助…
让我展示一下我目前预计的类图:
____________________________________ _____________________________________ | CustomizableObject | | System.Windows.Controls.UserControl | |____________________________________| |_____________________________________| | string XAMLHeader() | ▲ | string XAMLFooter() |◄--┐ | | CustomizableObject LoadObject() | \ | | <Possible other implementations> | \ | |____________________________________| \ | ▲ ▲ \ | | | \ | | | \ | _________________ ______________________ \ _____________________ | SpriteAnimation | | SpriteAnimationFrame | └---| CustomizableControl | |_________________| |______________________| |_____________________| ▲ ▲ | | | | ________ _____________ | Sprite | | SpriteFrame | |________| |_____________|
问题非常清楚:CustomizableObject和CustomizableControl对象树的分离—将UserControl插入树中的一个而不是两者。
将CustomizableObject的实现移动到派生类中没有实际意义,因为实现不会因类而异。 而且,如果多次实施,这将会令人困惑。 所以我真的不想让CustomizableObject成为一个接口。 接口解决scheme对我没有任何意义。 (接口从来没有真正对我很有意义,说实话…)
所以我再说一次,任何人有什么好主意? 这是一个真正的腌菜。 我想了解更多关于使我的对象树的接口工作,而不是反对它。 我使用WPF和C#这个简单的sprite引擎作为一个坚实的练习,比什么都重要。 这在C ++中很容易解决 – 但是我需要弄清楚如何在托pipe环境中解决这些问题,而不是在遇到困难的时候,把手放在空中,然后跑回Win32。
一种方法是使用带有接口的扩展方法来提供你的“派生类”实现,就像System.Linq.Queryable:
interface ICustomizableObject { string SomeProperty { get; } } public static class CustomizableObject { public static string GetXamlHeader(this ICustomizableObject obj) { return DoSomethingWith(obj.SomeProperty); } // etc } public class CustomizableControl : System.Windows.Controls.UserControl, ICustomizableObject { public string SomeProperty { get { return "Whatever"; } } }
用法:只要你有一个使用指令(或者在同一个命名空间中)定义扩展方法的命名空间:
var cc = new CustomizableControl(); var header = cc.GetXamlHeader();
你有两个select, 使用接口,或使用组合。 老实说,接口是非常强大的,读完这一行后
接口解决scheme对我没有任何意义。 (接口从来没有真正对我很有意义,说实话…)
我认为你应该学习如何正确使用它们。 也就是说,如果只有一些逻辑需要多个类,但这些类从相同的基类inheritance是没有意义的,只需创build一个类来封装该逻辑,并将该类的成员variables添加到类中这是给你的问题。 这样,所有的类都包含逻辑,但是在inheritance层次结构中可以分开。 如果这些类应该实现一个通用接口,那么使用接口。
我正在看这个, CustomizableObject
只是尖叫着被做成一个接口(因为每一个具体的types都可以转换为对象,这部分名称是多余的)。 你遇到的问题是,你不知道如何保留一些基本的逻辑,这些逻辑将被共享,或者只是随着实现而略有不同,而且你想把这个逻辑存储在树中,这样它就能够以多态的方式工作那个字?)。
你可以通过委托来达到这个目的。 我不确定哪些成员给你麻烦,但也许更像这样的事情:
____________________________________ _____________________________________ | ICustomizable | | System.Windows.Controls.UserControl | | | |_____________________________________| | Func<string> XAMLHeader; | ▲ | Func<string> XAMLFooter |◄--┐ | | ICustomizabl LoadObject() | \ | | <Possible other implementations> | \ | |____________________________________| \ | ▲ ▲ \ | | | \ | | | \ | _________________ ______________________ \ _____________________ | SpriteAnimation | | SpriteAnimationFrame | └---| CustomizableControl | |_________________| |______________________| |_____________________| ▲ ▲ | | | | ________ _____________ | Sprite | | SpriteFrame | |________| |_____________|
此外,你可能有一些真正属于你的CustomizableObjecttypes的真正静态的逻辑。 但是这可能是错误的:您在特定情况下build立了使用该types的types。 例如,从上下文看,您将创build这些控件和animation并在Windows窗体上使用它们。 要做的事情是从基础System.Windows.Forminheritance自己的表单,而这个新的表单types应该知道ICustomizableObject以及如何使用它。 这就是你的静态逻辑将去的地方。
这看起来有些尴尬,但是当您决定更改演示引擎时,它被certificate是准确的。 如果将此代码移植到WPF或Silverlight,会发生什么情况? 他们可能需要使用与Windows窗体不同的实现代码,而且您仍然可能需要更改您的CustomizableControl实现。 但是你的静态逻辑现在完全在正确的地方。
最后,你正在使用的LoadObject()方法对于我来说也是错误的地方。 你说你想让每一个Customizabletypes提供一个你可以调用的方法,知道如何加载/构造自己。 但是这真的是不同的东西。 您可能需要另一个名为IConstructable<T>
接口, IConstructable<T>
您的ICustomizabletypes实现( IConstructable<ICustomizable>
)。
看起来你将不得不诉诸接口和对象组成。
在这种情况下我使用mixin。 在许多语言中,mixins是一个强大的概念,可以在运行时为类添加function。 mixin在很多语言中都是众所周知的。 重新混合框架是一个将mixin技术带入.NET的框架。
这个想法很简单:用一个代表mixin的类属性装饰你的类。 在运行时,这个function将被添加到你的类中。 所以你可以模拟多重inheritance。
解决您的问题可能是使CustomizableObject混入。 你将需要这个重新混合框架。
[使用(CustomizableObjectMixin)] CustomizableControl:UserControl
请查看remix.codeplex.com了解更多详情。
我认为是一个解决scheme。
public interface IClassA { void Foo1(); void Foo2(); } public interface IClassB { void Foo3(); void Foo4(); } public class ClassA :IClassA { #region IClassA Members public void Foo1() { } public void Foo2() { } #endregion } public class ClassB :IClassB { #region IClassB Members public void Foo3() { } public void Foo4() { } #endregion } public class MultipleInheritance :IClassA, IClassB { private IClassA _classA; private IClassB _classB; public MultipleInheritance(IClassA classA, IClassB classB) { _classA = classA; _classB = classB; } public void Foo1() { _classA.Foo1(); } public void Foo2() { _classA.Foo2(); AddedBehavior1(); } public void Foo3() { _classB.Foo3(); AddedBehavior2(); } public void Foo4() { _classB.Foo4(); } private void AddedBehavior1() { } private void AddedBehavior2() { } }
类MultipleInheritance将新行为添加到两个不同的对象,而不会影响此对象的行为。 MultipleInheritance具有与交付对象相同的行为(inheritance两种行为)。 Sory为我的英语。 问候。