一种将基本类型转换为派生类型的方法

时间:2020-03-06 14:37:58  来源:igfitidea点击:

我不确定这是否是一件奇怪的事情,或者这是否是某种代码的味道...但是我想知道是否有一种方法(某种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)
    ;

我很早以前就问过这个问题