32

I heard the word Interface Duck Typing, but do not understand at all what is it? So I read a wiki about this and they said:

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.

But still could not understand what it. So I saw their program but they use dynamic keyword to call quack() & feather() function of all the classes.

I would request you all please explain in easy way what is Interface Duck Typing and how to implement in C# v2.0 because there is no dynamic keyword.

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();
    }
  }
}
BartoszKP
  • 34,786
  • 15
  • 102
  • 130
Thomas
  • 33,544
  • 126
  • 357
  • 626
  • 10
    http://ericlippert.com/2014/01/02/what-is-duck-typing/ – Soner Gönül Jan 22 '14 at 08:51
  • You can't (well unless you do ugly reflection), duck typing is unique to dynamic languages and doesn't really make a whole lot of sense to me in statically typed languages. I would say the Java and Groovy examples are better, as they actually presents a human that Can't quack... Because the most general consensus is that if it can "quack" it's a duck... meaning your Person is also a duck, as he can "Quack"... the outcome of his ability to "Quack" may be different, but he still can. – Jens Jan 22 '14 at 08:56
  • 2
    @Jens Go is statically typed but uses duck typing for interfaces. A really great feature IMO. – CodesInChaos Jan 22 '14 at 09:59
  • @CodesInChaos I don't know GO, but it sounds like a language that like many others has put it's foot in both camps... (Which is great btw.)... TypeScript does much the same thing, so in essence I guess you are right, it can make sense... – Jens Jan 22 '14 at 10:21
  • @PeoplesWhoKnowsAnswer is it similar to ADAPTER PATTERN ? – exexzian Jan 22 '14 at 10:26
  • "If it quacks like a duck, and walks like a duck, it's a duck". C# actually uses duck typing (from what I can tell) with foreach, check out section 8.8.4 – Joe Jan 22 '14 at 10:36

5 Answers5

29

C# has a nominal type system, so the compatibility of types is done based on their names. In your example you have two classes with a Quack method, however there is no way to write a method which can take instances of these two classes and invoke their Quack method.

In C# 2, the solution would be to introduce an interface and have both classes implement it:

public interface IQuack
{
    void Quack();
}

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

now you can create a method which take an IQuack instance and can call Human.Quack and Duck.Quack through it. In C#, methods are resolved 'early' at compile time, so you need to create a named type which supports the operations the method need so the compilation can succeed. Note there is still a runtime element to calling these methods, since the real implementation of IQuack.Quack needs to be resolved at runtime depending on the real type of the argument.

In a duck-typing system, no attempt is made to validate that a method exists before runtime. All that is required is that a given object supports the operation in that it has the right name and takes the required number of parameters (none in this case), hence the 'if it quacks like a duck' expression.

Duck typing in C# 2 can only be done using reflection, in this case you would accept an object argument and look for the required methods yourself:

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 makes this much simpler with dynamic:

public static void MakeQuack(dynamic duck)
{
    duck.Quack();
}
Lee
  • 142,018
  • 20
  • 234
  • 287
  • 2
    This is the only answer that actually answers how to accomplish this in C# 2.0 – Novaterata Sep 22 '14 at 19:40
  • @Lee: Very good answer. You said that it is easier with `dynamic`, can you please provide another example for a "dynamic" duck? I would be particularily interested in how to handle it if the method in the passed "duck" parameter does not exist. – Matt Jan 13 '15 at 11:21
  • @Matt - see update. I changed the reflection version of `MakeQuack` to throw an exception if no method exists to make it more consistent with the `dynamic` version. – Lee Jan 13 '15 at 11:51
  • That's a good idea, thank you for the update (also thanks for the dynamic example)! I noticed an interesting difference between the two: The reflection-based MakeQuack also calls static public methods with the name `Quack`, while the dynamic version only calls the non-static ones. – Matt Jan 13 '15 at 12:39
  • 1
    Generic functions are statically type checked in C++ hence following sentence is wrong: *In a duck-typing system, no attempt is made to validate that a method exists before runtime*. – Patrick Fromberg Nov 26 '17 at 17:02
  • @PatrickFromberg - I wouldn't call C++ templates duck typing, structural typing maybe. Duck typing only concerns itself with the members actually accessed at runtime. – Lee Nov 26 '17 at 21:45
  • @Lee, your definition of duck typing contradicts Wikipedia but Wikipedia may be wrong. Whose definition are you using? I just looked up the definition of structural typing (also in Wikipedia) and C++ function templates using type category constraints (as in C++20) actually do remind me of that. – Patrick Fromberg Nov 26 '17 at 22:20
  • @PatrickFromberg - The wikipedia page for duck typing explicitly [compares](https://en.wikipedia.org/wiki/Duck_typing#Templates_or_generic_types) duck typing and C++ templates and it supports my definition that duck typing is a runtime mechanism. Only the methods actually called at runtime need to be compatible. Having said that I'm not sure duck typing has a formal definition in type theory so there could be inconsistent definitions for it. – Lee Nov 26 '17 at 22:36
  • "In a duck-typing system, no attempt is made to validate that a method exists before runtime" this is false, Golang uses duck typing and checks that the Quack method exists during compile time. TypeScript is similar. Duck typing simply means that types do not need to explicitly share an interface to be interchangeable. – cat_in_hat Dec 07 '19 at 03:30
  • @cat_in_hat - Go uses [structural typing](https://en.wikipedia.org/wiki/Structural_type_system) not duck typing: "[structural typing] contrasts with nominative systems, where comparisons are based on the names of the types or explicit declarations, and duck typing, in which only the part of the structure accessed at runtime is checked for compatibility." – Lee Dec 07 '19 at 11:09
  • @Lee thanks for the clarification, I see now that there is a subtle difference – cat_in_hat Dec 10 '19 at 04:03
12

It would say it is a way of coding where the you tell the compiler:

"Hey trust me I know what methods and properties this object supports. You don't need to check them for me whilst I code."

Once you run your app the compiler will go: "Ok lets see if I could trust you. Let me do some runtime binding."

If you then made a mistake, such as using an unsupported method, the compiler will shout: "Hey man, this is not supported! Check my RuntimeBinderException!"

Atomic Star
  • 5,427
  • 4
  • 39
  • 48
10

Duck typing allows an object to be passed in to a method that expects a certain type even if it doesn’t inherit from that type. All it has to do is support the methods and properties of the expected type in use by the method. I emphasize that last phrase for a reason. Suppose we have a method that takes in a duck instance, and another method that takes in a rabbit instance. In a dynamically typed language that supports duck typing, I can pass in my object to the first method as long as my object supports the methods and properties of duck in use by that method. Likewise, I can pass my object into the second method as long as it supports the methods and properties of rabbit called by the second method. Is my object a duck or is it a rabbit? Like the above image, it’s neither and it’s both. In many (if not most) dynamic languages, my object does not have to support all methods and properties of duck to be passed into a method that expects a duck. Same goes for a method that expects a rabbit.It only needs to support the methods and properties of the expected type that are actually called by the method.

Please refer this to get an idea about Duck Typing

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

tarzanbappa
  • 4,930
  • 22
  • 75
  • 117
5

About Duck Typing:

We don't need to know what the object is, but we just want to let the object do something if it can do.

Example:

Example, if here are the things that we want the following objects do.

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

And, here is the result after we request the above objects do the things. enter image description here

So, we don't need to check what the object is, but we can let it do something enough. Here is the code that I have written in 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();
    }
KHACHORNCHIT
  • 2,222
  • 23
  • 19
0

You can use Events and exploit C# best suitable overload functions.

Hopefully, it will be useful :)

To get something Like a duck typing (.Net 4.+):

using System.Collections;
using System.Collections.Generic;
public interface  IAny
{
    void InvokeGetterEvent();
}
 public class AnyValueTypeDuck<T, V> : IAny
    where V : AnyValueTypeDuck<T, V>
 {
    public static event System.Action<V> GetterEvent;
    public T Data;
    public void InvokeGetterEvent()
    {
        GetterEvent.Invoke((V)this);
    }
 }

// Then create some concrete classes:
// Example :
public class LifeConcreteProperty : AnyValueTypeDuck<int, LifeConcreteProperty>
{
}
public class ManaConcreteProperty : AnyValueTypeDuck<float, ManaConcreteProperty>
{
}

// Now to finally use it :
public class UserClass
{
    List<IAny> allDuckTypes = new List<IAny>();

    public void GetDucketTypeClass(IAny anyDuckObject)
    {
        LifeConcreteProperty.GetterEvent += GetDucketType;
        ManaConcreteProperty.GetterEvent += GetDucketType;
        anyDuckObject.InvokeGetterEvent();
        // it will propagate to event and will invoke 
        // best suitable overload method (GetDucketType)
        LifeConcreteProperty.GetterEvent -= GetDucketType;
        ManaConcreteProperty.GetterEvent -= GetDucketType;
    }

    public void GetDucketType(LifeConcreteProperty originalClass)
    {
        // Your efforts go here
        int value =  originalClass.Data;
    }
    public void GetDucketType(ManaConcreteProperty originalClass)
    {
        // Your efforts go here
        float value =  originalClass.Data;
    }
}
General Grievance
  • 4,555
  • 31
  • 31
  • 45
Roma Fedor
  • 19
  • 7