c# - 什么是界面鸭子类型?

标签 c# oop

我听说过 Interface Duck Typing 这个词,但完全不明白它是什么?所以我读了一个关于这个的 wiki,他们说:

In computer programming with object-oriented programming languages, duck typing is a style of typing in which an object's methods and properties determine the valid semantics, rather than its inheritance from a particular class or implementation of an explicit interface. The name of the concept refers to the duck test.

但是还是看不懂是什么东西。所以我看到了他们的程序,但他们使用 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();
    }
  }
}

最佳答案

C# 有一个名义类型系统,因此类型的兼容性是根据它们的名称来完成的。在您的示例中,您有两个带有 Quack 方法的类,但是无法编写一个方法来获取这两个类的实例并调用它们的 Quack 方法。

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

public interface IQuack
{
    void Quack();
}

public class Duck : IQuack { }
public class Human : IQuack { }

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

在鸭子类型系统中,不会尝试在运行前验证方法是否存在。所需要的只是一个给定的对象支持该操作,因为它具有正确的名称并采用所需数量的参数(在本例中没有参数),因此是“如果它像鸭子一样嘎嘎叫”表达式。

C# 2 中的 Duck 类型只能使用反射来完成,在这种情况下,您将接受一个 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();
}

关于c# - 什么是界面鸭子类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21278078/

相关文章:

c# - 使用 C# 将文件写入 URL 位置

c# - 为什么 C# 没有词法嵌套函数?

c# - 关闭/销毁 FtpWebRequest

objective-c - 类和父类(super class)之间的双向通信

python - python 中的面向对象设计问题,has-a 与 is-a

c# - 在应用程序简历中隐藏软键盘

c# - ASP.NET Core CORS 请求被阻止;为什么我的 API 没有应用正确的 header ?

python - 类和变量

java - 从订单 ArrayList 中删除项目

c++ - C++中的对象创建和成员声明