c#polymorphism派生类到其他派生类

时间:2011-09-20 10:47:42

标签: c# .net polymorphism

我有一个类,例如Tile,派生类TileA,TileB ... TileF。

现在我希望TileF类通过调用TileE来改变。 还有TileE到TileD,你可以看到patern。 我可以直接在TileF中将其更改为。

我正在查看Activator.CreateInstance(),但这给了我一个对象类,而不是想要的派生类。

我该如何解决这个问题?

我在主循环中执行此操作,我在其中指定了Tile tile = TileF; 然后我想做一些事情:tile.change()并且它会在new TileE

中发生变化

某种代码:

Class Tile{
   public abstract int Number{ get; }
}
Class TileF : Tile{
public override int Number
        {
            get
            {
                return 1;
            }
        }
} 
Class TileE : Tile{
public override int Number
        {
            get
            {
                return 2;
            }
        }
} 

Class Main{
Tile tile = new TileF;
//change tile to TileE
tile = tile.ToNextTileType();

}

4 个答案:

答案 0 :(得分:2)

TileETileF是兄弟姐妹时,即当他们从一个共同的基类派生时,你不能直接转换它们。

有几种可能的解决方案,但您没有提供太多细节。

我想也许你不应该使用继承。一个简单的enum TileType可以解决你的问题吗?

答案 1 :(得分:0)

您可能希望查看接口。当您引用接口类型的类型时,接口允许将不相关的对象视为相同的对象,例如

class ClassOne : ICommon;
class ClassTwo : ICommon;
class ClassThree : ICommon;

ClassOne x = new ClassOne();
ClassTwo y = new ClassTwo();
ClassThree z = new ClassThree();

List<ICommon> data = new List<ICommon>();
data.Add(x);
data.Add(y);
data.Add(z);

foreach(ICommon item in data)
{
    item.InterfaceMethodOne();
}

这可能不是你想要的,但值得研究。

詹姆斯: - )

答案 2 :(得分:0)

对象的静态和动态类型之间存在差异。可以更改对象的静态类型,即您可以编写BaseType base = (BaseType)new DerivedType();。更改实例的静态类型称为强制转换

编译器将限制对BaseType及其所有基类型中存在的方法,字段和属性的调用。但是,对象的动态类型可能永远不会更改,在这种情况下,base仍然具有动态类型DerivedType。在这种情况下,条件if (base is DerivedType)将返回true。您只能通过实例化目标类型的新对象来“更改”动态类型,并将所需的值复制到新实例。此过程称为映射

顺便说一句,Activator.CreateInstance只会为您提供静态类型object的实例,但可能会使用不同的动态类型。您可以通过将静态类型强制转换为您知道对象应具有的类型来更改静态类型:(DerivedType)Activator.CreateInstance(typeof(DerivedType))。您也可以使用泛型变体,然后在方法中完成此演员:Activator.CreateInstance<DerivedType>()。在语义上没有区别,除了通用变体更容易阅读。

编辑:

这会解决您的问题吗?

public abstract class Tile {
  public abstract int Number { get; }
  public abstract Tile Advance();
}

public class TileA : Tile {
  public override int Number { get { return 1; } }
  public override Tile Advance() { return new TileB(); }
}

public class TileB : Tile {
  public override int Number { get { return 2; } }
  public override Tile Advance() { return new TileC(); }
}

public class TileC : Tile { ... }

您还可以在抽象类中定义“状态机”,如下所示:

public abstract class Tile {
  public abstract int Number { get; }
  public sealed Tile Advance() {
    if (this is TileA) {
      return new TileB();
    else if (this is TileB) {
      return new TileC();
    }
  }
}

另一种选择当然是将状态机完全建模在一个对象中:

public enum TileState { TileA, TileB, TileC };
public class Tile {
  private TileState state = TileState.TileA; // initial state

  public int Number {
    get {
      switch (state) {
        case TileState.TileA: return 1;
        case TileState.TileB: return 2;
        ...
        default: return -1; // or throw exception
      }
    }
  }

  public void Advance() {
    switch (state) {
      case TileState.TileA: state = TileState.TileB; break;
      case TileState.TileB: state = TileState.TileC; break;
      ...
      default: // exception ?
    }
  }
}

在最后一个示例中,对象的行为会根据状态变量而变化。它不是一个新的实例,但它可以做一些完全不同的事情。我希望这可能有所帮助。

答案 3 :(得分:0)

我在设计TileF / TileE等时犯了错误。制作TileN已经足够了,其中一个属性正在替换一个tile的内部工作。这样我就不必替换一个类,从而避免了这个问题。