如何从其父接口获取实际类型的派生类

如何从其父接口获取实际类型的派生类

问题描述:

假设我们有这样的代码部分:

Let's say we have a code portion like this:

IProduct product = ProductCreator.CreateProduct(); //Factory method we have here
SellThisProduct(product);

//...

private void SellThisProduct(IProduct product)
{
  //.. Do something here
}

//...

internal class Soda : IProduct
{}

internal class Book : IProduct
{}

如何推断在方法中SellThisProduct()方法中实际传递的产品?

How can I infer which product is actually passed into SellThisProduct() method in the method?

我想如果我说GetType()或者它可能会返回IProduct类型。

I think if I say GetType() or something it will probably return the IProduct type.

GetType 获取对象的确切运行时类型。从 文档

GetType gets you the exact runtime type of an object. From the documentation:


代表当前实例的确切运行时类型的Type实例。

The Type instance that represents the exact runtime type of the current instance.

您还可以使用来确定对象是否是特定类型的实例:

You can also use is to determine if an object is an instance of a specific type:

var noise = (obj is Velociraptor) ? "SKREEE!" : "<unknown>";

为什么需要确切的运行时类型?接口的整个点是你应该隐藏通用接口背后的实现细节。如果你需要根据类型采取行动,这是一个很大的暗示,你违反了它提供的封装。

Why do you need the exact runtime type, though? The entire point of an interface is that you should be hiding the implementation details behind the common interface. If you need to take an action based on the type, that's a big hint that you're violating the encapsulation it provides.

一个替代方法是使用多态性: p>

One alternative is to use polymorphism:

public interface IVocalizer { string Talk(); }

public class Doorbell : IVocalizer {
  public string Talk() { return "Ding-dong!" }
}
public class Pokemon : IVocalizer {
  public string Talk() {
    var name = this.GetType().ToString();
    return (name + ", " + name + "!").ToUpper(); } // e.g., "PIKACHU, PIKACHU!"
}
public class Human : IVocalizer {
  public string Talk() { return "Hello!"; }
}

由于这三种类型完全不相关,类型没有意义。但为了表示它们具有相同的产生噪声的能力,我们可以使用IVocalizer接口,然后要求每个人产生噪声。这是一个更清洁的方法:现在你不需要关心什么类型的对象,当你想要它发出一个噪音:

Since these three types aren't related at all, inheritance from a common type doesn't make sense. But to represent that they share the same capability of making noise, we can use the IVocalizer interface, and then ask each one to make a noise. This is a much cleaner approach: now you don't need to care what type the object is when you want to ask it to make a noise:

IVocalizer talker = new ???();  // Anything that's an IVocalizer can go here.

// elsewhere:
Console.WriteLine(talker.Talk());    // <-- Now it doesn't matter what the actual type is!
                                     //   This will work with any IVocalizer and you don't
                                     //   need to know the details.