我不确定这是否是一件奇怪的事情,或者是否有一些代码闻起来...但我想知道是否有某种方式(某种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()); }
我知道这似乎很傻,但有没有办法完成这种事情?
"管理"语言并不合理.这是向下转型,并有处理一下,整整你所说的原因,任何理智的一路下跌(子类,提供超过基类-在哪里呢这个"更"是从哪里来的?).如果您确实需要特定层次结构的类似行为,则可以将构造函数用于将基类型作为原型的派生类型.
可以用反射来构建一些处理简单情况的东西(更具体的类型没有添加状态).一般来说,只需重新设计即可避免此问题.
编辑:Woops,无法在基类/派生类型之间编写转换运算符.微软试图"保护你"对付自己的奇怪之处.好吧,至少他们没有像太阳那样差.
尝试合成而不是继承!
在我看来,你最好将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页):
通过组合重用代码组合为Apple提供了另一种方法,可以重用Fruit的peel()实现.Apple不是扩展Fruit,而是可以保存对Fruit实例的引用,并定义自己的peel()方法,只需在Fruit上调用peel()即可.
就个人而言,我不认为在这种情况下使用继承的麻烦是值得的.而只是在构造函数中传递基类实例并通过成员变量访问它.
private class ExtendedClass //: BaseClass - like to inherit but can't { public readonly BaseClass bc = null; public ExtendedClass(BaseClass b) { this.bc = b; } public int ExtendedProperty { get { } } }
向下转换是有道理的,如果你有一个派生类的对象,但它被基类类型的引用引用,并且由于某种原因你希望它返回由派生类类型引用引用.换句话说,您可以向下转换以反转先前向上转换的效果.但是,您不能拥有由派生类类型的引用引用的基类对象.
我不是说我推荐这个.但是您可以将基类转换为JSON字符串,然后将其转换为派生类.
SomeDerivedClass layer = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(BaseClassObject));
不,这是不可能的.在像C#这样的托管语言中,它只是不起作用.即使编译器允许,运行时也不会允许它.
你自己说这看起来很傻:
SomeBaseClass class = new SomeBaseClass(); SomeDerivedClass derClass = (SomeDerivedClass)class;
那么问问自己,class
实际上是一个实例SomeDerivedClass
吗?不,所以转换毫无意义.如果需要转换SomeBaseClass
为SomeDerivedClass
,则应提供某种转换,无论是构造函数还是转换方法.
听起来好像你的类层次结构需要一些工作.通常,不应该将基类实例转换为派生类实例.通常应该存在不适用于基类的数据和/或功能.如果派生类功能适用于基类的所有实例,则它应该被卷入基类或拉入不属于基类层次结构的新类.
C#语言不允许这样的操作符,但您仍然可以编写它们并且它们可以工作:
[System.Runtime.CompilerServices.SpecialName] public static Derived op_Implicit(Base a) { ... } [System.Runtime.CompilerServices.SpecialName] public static Derived op_Explicit(Base a) { ... }