什么是界面鸭打字?

我听到了接口鸭打字这个词,但根本不明白它是什么? 所以我读了一篇关于这个的维基,他们说:

在使用面向对象编程语言的计算机编程中,duck typing是一种键入方式,其中对象的方法和属性确定有效语义,而不是从特定类或显式接口的实现inheritance。 概念的名称是指鸭子测试。

但仍然无法理解它是什么。 所以我看到了他们的程序,但他们使用dynamic关键字来调用所有类的quack()feather()函数。

我会请求大家请简单解释什么是Interface Duck Typing以及如何在C#v2.0中实现,因为没有dynamic关键字。

 using System; namespace DuckTyping { public class Duck { public void Quack() { Console.WriteLine("Quaaaaaack!"); } public void Feathers() { Console.WriteLine("The duck has white and gray feathers."); } } public class Person { public void Quack() { Console.WriteLine("The person imitates a duck."); } public void Feathers() { Console.WriteLine("The person takes a feather from the ground and shows it."); } } internal class Program { private static void InTheForest(dynamic duck) { duck.Quack(); duck.Feathers(); } private static void Game() { Duck donald = new Duck(); Person john = new Person(); InTheForest(donald); InTheForest(john); } private static void Main() { Game(); } } } 

Duck输入允许将对象传递给期望某种类型的方法,即使它不从该类型inheritance。 它所要做的就是支持该方法使用的预期类型的​​方法和属性。 我强调最后一句话是有原因的。 假设我们有一个接受duck实例的方法,另一个接受Rabbit实例的方法。 在支持duck typing的动态类型语言中,只要我的对象支持该方法使用的duck的方法和属性,我就可以将我的对象传递给第一个方法。 同样,我可以将我的对象传递给第二种方法,只要它支持第二种方法调用的兔子的方法和属性。 我的对象是鸭子还是兔子? 就像上面的图像一样,它既不是,也是两者兼而有之。 在许多(如果不是大多数)动态语言中,我的对象不必支持将duck的所有方法和属性传递给期望鸭子的方法。 对于需要兔子的方法也是如此。它只需要支持方法实际调用的期望类型的方法和属性。

请参考这个以了解鸭子打字

http://haacked.com/archive/2007/08/19/why-duck-typing-matters-to-c-developers.aspx/

C#具有标称类型系统,因此类型的兼容性基于它们的名称来完成。 在您的示例中,您有两个使用Quack方法的类,但是无法编写可以接受这两个类的实例并调用其Quack方法的方法。

在C#2中,解决方案是引入一个接口并让两个类实现它:

 public interface IQuack { void Quack(); } public class Duck : IQuack { } public class Human : IQuack { } 

现在你可以创建一个接受IQuack实例的方法,并可以通过它调用Human.QuackDuck.Quack 。 在C#中,方法在编译时“早期”解析,因此您需要创建一个支持该方法所需操作的命名类型,以便编译成功。 请注意,仍然有一个运行时元素来调用这些方法,因为IQuack.Quack的实际实现需要在运行时根据参数的实际类型进行解析。

在鸭子类型系统中,没有尝试在运行时之前validation方法是否存在。 所需要的只是给定的对象支持操作,因为它具有正确的名称并且获取所需数量的参数(在这种情况下没有),因此’如果它像鸭子一样嘎嘎叫’表达式。

在C#2中输入鸭只能使用reflection来完成,在这种情况下,您将接受一个object参数并自己查找所需的方法:

 public static void MakeQuack(object duck) { MethodInfo quackMethod = duck.GetType().GetMethod("Quack", Type.EmptyTypes, null); if (quackMethod!=null) { quackMethod.Invoke(duck, new object[] { }); } else { throw new ArgumentException("No Quack() method found on target"); } } 

C#4使dynamic更加简单:

 public static void MakeQuack(dynamic duck) { duck.Quack(); } 

它会说这是一种编码方式,你告诉编译器:

“嘿,相信我,我知道这个对象支持哪些方法和属性。在编写代码时,你不需要为我检查它们。”

一旦你运行你的应用程序,编译器将会: “好的,看看我是否可以信任你。让我做一些运行时绑定。”

如果你犯了一个错误,比如使用不支持的方法,编译器就会喊: “嘿,伙计,这是不支持的!检查我的RuntimeBinderException!”

关于鸭子打字:

我们不需要知道对象是什么,但我们只是想让对象做一些事情。

例:

例如,如果这是我们想要以下对象所做的事情。

 PleaseWalk(new Dog()); PleaseRun(new Duck()); PleaseWalk(new Cup()); PleaseFly(new Man()); PleaseFly(new Bird()); 

并且,这是我们请求上述对象完成后的结果。 在此处输入图像描述

因此,我们不需要检查对象是什么,但我们可以让它做足够的事情。 这是我用C#编写的代码。

 private void PleaseWalk(object obj) { string Method = "Walk"; MethodInfo walkMethod = obj.GetType().GetMethod(Method, Type.EmptyTypes, null); if (walkMethod != null) { walkMethod.Invoke(obj, new object[] { }); } else { Console.WriteLine(string.Format("I can not {0} because {1}", Method, WhoAreYou(obj))); } } private string WhoAreYou(object unknown) { MethodInfo whoAreYou = unknown.GetType().GetMethod("WhoAreYou", Type.EmptyTypes, null); return whoAreYou.Invoke(unknown, new object[] { }).ToString(); }