从基铸造到派生铸造

本文关键字:派生 | 更新日期: 2023-09-27 18:17:39

是否可以将对象从基类强制转换为派生类?例如,假设我有一个基材:Animal。从这里我得到了其他几个类:Cat, Dog。现在我需要一个Animal,但目前类型并不重要。

Animal blankCanvas = new Animal();

一路走来,我改变了主意,现在想把Animal改成Dog。然而,我不明白我该如何去做。我知道将动物转换为狗的业务规则,但我只是不知道如何实现它。

从基铸造到派生铸造

是的,您可以将基引用强制转换为派生引用。

但是你似乎想转换一个实例。这不是铸造,也不是直接可能的。

你的逻辑应该是这样的,当你创建它的时候你就知道你想要什么类型。

Animal blankCanvas = null;
...
blankCanvas = new Dog();

为了帮助您保持正确的路径,将Animal定义为abstract class
毕竟,Animal的实例代表什么?

您可以像这样在派生类上使用静态方法:

/// <summary>
/// Dog.
/// </summary>
class Dog : Animal
{
    /// <summary>
    /// Initializes a new instance of the <see cref="Dog"/> class.
    /// </summary>
    /// <param name="type">The type.</param>
    public Dog(string type)
        : base(type)
    { }
    /// <summary>
    /// Gets a dog from an animal.
    /// </summary>
    /// <param name="animal">The animal.</param>
    /// <returns></returns>
    public static Dog FromAnimal(Animal animal)
    {
        return new Dog(animal.Type);
    }
}
/// <summary>
/// Animal.
/// </summary>
class Animal
{
    /// <summary>
    /// Gets or sets the type.
    /// </summary>
    /// <value>The type.</value>
    public string Type { get; private set; }
    /// <summary>
    /// Initializes a new instance of the <see cref="Animal"/> class.
    /// </summary>
    /// <param name="type">The type.</param>
    public Animal(string type)
    {
        this.Type = type;
    }
}

或者使用单个工厂类来管理所需的所有转换。

如果不编写自定义转换,就无法做到这一点。也许更好的做法是更早地决定需要什么样的派生类型,并创建该类型的实例。

大多数情况下,当类型系统以这种方式与您对抗时,您需要重新设计您的体系结构。

据我所知,你不能用强制转换做到这一点,但你可以在Dog中有一个构造函数,它可以接受和animal作为参数,就像这样:

Public Dog(Animal pAnimal)
{
    //do stuff...
}

你的类的实例一旦"生为动物"将作为Animal度过它的一生。您可以尝试将其强制转换为派生类,但由于实例本身仍然是Animal,因此在任何情况下都将失败。

这里有一些建议如何将其更改为其他类:

您可以通过使用静态方法显式地实现到另一个类的自定义转换,例如,您可以实现如下内容:

public class Cat : Animal
{
 public Cat FromAnimal(Animal animal)
 {
   return new Cat(animal) {Eyes = Color.Blue, ... };
 }
}

您可以先序列化实例,然后使用支持在另一个类中反序列化的特定序列化器对实例进行反序列化。

您可以使用派生类型的显式返回类型实现实例的深度克隆。

然后你只需用新板Cat替换旧的Animal并在任何地方使用它…