如何从其父接口获取派生类的实际类型
假设我们有一个像这样的代码部分:
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()方法?
我想如果我说GetType()或其他东西它可能会返回IProduct类型。
GetType
您提供对象的确切运行时类型。 从文档 :
Type实例,表示当前实例的确切运行时类型。
您还可以使用is
来确定对象是否是特定类型的实例:
var noise = (obj is Velociraptor) ? "SKREEE!" : "";
但是,为什么需要确切的运行时类型? 接口的全部内容是您应该隐藏公共接口背后的实现细节。 如果你需要根据类型采取行动,这是一个很大的暗示,你违反了它提供的封装。
一种替代方法是使用多态性:
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(); } // eg, "PIKACHU, PIKACHU!" } public class Human : IVocalizer { public string Talk() { return "Hello!"; } }
由于这三种类型根本不相关,因此从常见类型inheritance是没有意义的。 但是为了表示它们具有相同的发出噪声的能力,我们可以使用IVocalizer接口,然后让每个人发出噪音。 这是一种更清洁的方法:现在,当您要求它发出噪音时,您无需关心对象的类型:
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.
Object.GetType
返回实例的确切运行时类型 。 这就是你应该使用的。
虽然,一般来说,你根本不应该关心接口的运行时类型 – 如果你正在编写代码来确定它,它可能反映了你的设计中的某个错误。
实际上,接口名称IProduct
已经有点代码味道了。 这本身并没有错,但接口意味着定义特定对象上可用的操作 ,即它的作用 。 IProduct
这个名称似乎在描述它是什么,而不是它的作用 ,它更适合抽象基类。 请注意,这不是一个“规则”,但它是一个很好的指导方针。
在编写依赖于抽象类型(基类或接口)的方法/类时,如果发现依赖于更多派生类型或特定实现,则意味着您的抽象类型是贫血的(没有足够的function)要有效地使用),或者你的依赖关系有太多耦合(取决于实现细节而不是抽象)。
考虑扩展Product
/ IProduct
以执行更多操作,或通过方法重载使您的依赖项实际处理特定的产品类型。
虽然GetType()将返回实际类型,但您应该使用is
运算符。
通常,您不需要这样做。 通常,您所做的只是将行为推迟到子类并通过接口调用它。 例如,如果您对Soda与Book有不同的要求(例如,Soda需要征税,而Book不需要),那么您将在界面上创建一个Sell方法,然后在SellThisProduct()方法中创建, d只需在对象上调用Sell()方法即可。
public interface IProduct { public decimal Sell(); // computes price ... }
…..
IProduct product = ProductCreator.CreateProduct(); //Factory Method we have here SellThisProduct(product); //... private void SellThisProduct(IProduct product) { var price = product.Sell(); ... } internal class Soda : IProduct { public decimal Sell() { this.Price + TaxService.ComputeTax( this.Price ); } } internal class Book : IProduct { public decimal Sell() { return this.Price; } }
if (product is Book) { ... } else if (product is Soda) { ... }
typeof(产品)将返回IProduct。
product.GetType()实际上将返回对象的派生类型,因为它是一个成员函数。