一种将基本类型转换为派生类型的方法
我不确定这是否是一件奇怪的事情,或者这是否是某种代码的味道...但是我想知道是否有一种方法(某种oop模式会很好)"投射"基本类型为其派生类型的形式。我知道这没有多大意义,因为派生类型将具有父级不提供的其他功能,这从根本上来说并不健全。但是有什么方法可以做到这一点吗?这是一个代码示例,以便我可以更好地解释我的要求。
public class SomeBaseClass { public string GetBaseClassName {get;set;} public bool BooleanEvaluator {get;set;} } public class SomeDerivedClass : SomeBaseClass { public void Insert(SqlConnection connection) { //...random connection stuff cmd.Parameters["IsItTrue"].Value = this.BooleanEvalutar; //... } } public static void Main(object[] args) { SomeBaseClass baseClass = new SomeBaseClass(); SomeDerivedClass derClass = (SomeDerivedClass)baseClass; derClass.Insert(new sqlConnection()); }
我知道这看起来很愚蠢,但是有什么办法可以完成这种事情吗?
解决方案
听起来不太好,使用"托管"语言。这是垂头丧气的,并且没有合理的方法来处理它,这正是我们所描述的原因(子类比基类提供了更多的"更多"来源)。如果确实希望特定层次结构具有类似的行为,则可以将构造函数用于派生类型,这些派生类型会将基本类型作为原型。
可以用反射来构建一些可以处理简单情况的东西(更具体的类型,它们没有加法状态)。通常,只需重新设计就可以避免该问题。
编辑:糟糕,无法在基本/派生类型之间编写转换运算符。微软试图"保护我们"免受自己的侵害的怪异之处。嗯,至少它们不比Sun差。
那行不通。请转到由编译错误链接的帮助页面。
最好的解决方案是在此处使用工厂方法。
这被称为向下转换,Seldaek关于使用"安全"版本的建议是正确的。
这是带有代码示例的相当不错的描述。
如果我们有一个派生类的对象,但是由基类类型的引用来引用,并且由于某种原因,我们希望它被派生类类型的引用所引用,那么向下转换是有意义的。换句话说,我们可以向下转换以反转先前向上转换的效果。但是我们不能通过派生类类型的引用来引用基类的对象。
不,这是不可能的。在像C#这样的托管语言中,它将无法正常工作。即使编译器允许运行时,运行时也不允许这样做。
我们自己说这似乎很愚蠢:
SomeBaseClass class = new SomeBaseClass(); SomeDerivedClass derClass = (SomeDerivedClass)class;
因此,问问自己," class"是否实际上是" SomeDerivedClass"的实例?不,因此转换没有任何意义。如果需要将" SomeBaseClass"转换为" SomeDerivedClass",则应提供某种转换,构造函数或者转换方法。
听起来好像类层次结构需要一些工作。通常,不可能将基类实例转换为派生类实例。通常应该存在不适用于基类的数据和/或者功能。如果派生类功能适用于基类的所有实例,则应将其汇总到基类中或者拉入不属于基类层次结构的新类中。
这是不可能的,因为我们将如何获得派生类所具有的"额外"价值。实例化实例时,编译器将如何知道意思是derivedClass1,而不是derivedClass2?
我认为我们真正要寻找的是工厂模式或者类似的模式,因此我们可以实例化对象,而无需真正知道要实例化的显式类型。在示例中,使用" Insert"方法将是工厂返回实现的实例的接口。
是的,这是一种代码味道,几乎可以确定继承链已损坏的事实。
我的猜测(从有限的示例中得出)是,我们希望DerivedClass在SomeBaseClass的实例上进行操作,以便" DerivedClass具有SomeBaseClass",而不是" DerivedClass是SomeBaseClass"。这被称为"有利于继承而不是继承"。
尝试组成而不是继承!
在我看来,最好将SomeBaseClass的实例传递给SomeDerivedClass(它将不再派生基类,因此应将其重命名)
public class BooleanHolder{ public bool BooleanEvaluator {get;set;} } public class DatabaseInserter{ BooleanHolder holder; public DatabaseInserter(BooleanHolder holder){ this.holder = holder; } public void Insert(SqlConnection connection) { ...random connection stuff cmd.Parameters["IsItTrue"].Value = holder.BooleanEvalutar; ... } } public static void Main(object[] args) { BooleanHolder h = new BooleanHolder(); DatabaseInserter derClass = new DatabaseInserter(h); derClass.Insert(new sqlConnection); }
查看http://www.javaworld.com/javaworld/jw-11-1998/jw-11-techniques.html(第3页):
Code reuse via composition Composition provides an alternative way for Apple to reuse Fruit's implementation of peel(). Instead of extending Fruit, Apple can hold a reference to a Fruit instance and define its own peel() method that simply invokes peel() on the Fruit.
正如其他人指出的那样,我们建议的强制转换实际上是不可能的。
可以引入Decorator模式(Head First提取)吗?
我们是否考虑过一个接口,基类和派生类当前都将实现什么接口?我不知道我们为什么要执行这种方式的细节,但它可能会起作用。
我不知道为什么没有人这么说,我可能会错过一些东西,但是我们可以使用as关键字,并且如果需要执行if语句,请使用if。
SomeDerivedClass derClass = class as SomeDerivedClass; //derClass is null if it isnt SomeDerivedClass if(class is SomeDerivedClass) ;
我很早以前就问过这个问题