简体   繁体   English

从基地铸造到衍生?

[英]Casting from Base To Derived?

Is it possible to cast an object from a base to a derived one? 是否可以将对象从基础转换为派生对象? For instance, let's say I have one base object: Animal . 例如,假设我有一个基础对象: Animal From this I have derived a couple of other classes: Cat , Dog . 由此我得出了几个其他类: CatDog Now I need an Animal but the type at this moment doesn't really matter. 现在我需要一个Animal但此刻的类型并不重要。 So, 所以,

Animal blankCanvas = new Animal();

Along the way I changed my mind and now want to change that Animal to a Dog . 一路走来,我改变了主意,现在想把那只Animal改成Dog However, I don't understand how I would go about doing that. 但是,我不明白我会怎么做。 I know the business rules to convert from an Animal to a Dog but I just don't know how to implement that. 我知道从Animal转换为Dog的业务规则,但我不知道如何实现它。

Yes, you can cast a base reference to a derived reference. 是的,您可以对派生引用强制转换基础引用。

But you seem to want to convert an instance. 但是你似乎想转换一个实例。 That is not casting and it is not directly possible. 这不是铸造,也不是直接可能的。

Your logic should be such that you know what type you want at the point when you create it. 您的逻辑应该是这样的,以便您在创建它时知道您想要的类型。

The following could make sense: 以下内容可能有意义:

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

To help you to keep the correct path, define Animal as an abstract class 为了帮助您保持正确的路径,请将Animal定义为abstract class
After all, what does an instance of Animal represent? 毕竟, Animal一个实例代表什么?

You can either use a static method on the derived class like this: 您可以在派生类上使用静态方法,如下所示:

/// <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;
    }
}

Or use a single factory class to manage all the conversions you need. 或者使用单个工厂类来管理所需的所有转换。

There is no way to do this without writing a custom conversion. 没有编写自定义转换就无法执行此操作。 Probably a better thing to do would be to decide much earlier what kind of derived type that you need and create an instance of that. 可能更好的做法是更早地决定你需要什么样的派生类型并创建一个实例。

Most of the time when the type system is going to fight you in this way you need to redesign your architecture. 大多数情况下,类型系统以这种方式打击你,你需要重新设计你的架构。

As far as I know you can't do that with a cast, but you could have a constructor in Dog that would accept and animal as a parameter like this: 据我所知,你不能用强制转换做到这一点,但是你可以在Dog中有一个构造函数来接受和动物作为这样的参数:

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

The instance of your class once "born as animal" will live its life as an Animal . 类一旦“出生动物”的实例将信守其生活的Animal You can try to cast it to derived class, but since the instance itself remains Animal it will fail in all cases. 您可以尝试将其强制转换为派生类,但由于实例本身仍为Animal因此在所有情况下都会失败。

Here are some suggestions how you can change it to other class: 以下是如何将其更改为其他类的一些建议:

You can implement a custom conversion to another class by implementing it explicitly using a static methods, for example, you can implement something like: 您可以通过使用静态方法显式实现自定义转换到另一个类,例如,您可以实现以下内容:

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

You can serialize and then deserialize your instance using certain serializers that support deserializing in another class. 您可以使用支持在另一个类中反序列化的某些序列化程序来序列化然后反序列化您的实例。

You can Implement deep cloning of your instance with explicit return types of derived types. 您可以使用显式返回类型的派生类型实现实例的深度克隆。

Then you just substitute your old Animal with a new-bord Cat and use it everywhere... 那么你只需要用一只新的Cat替换你的旧Animal并在任何地方使用它......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM