Question

Today we had a strange happening with a close() method.

Here is the code in doubt:

interface ICloseable
{
    void Close();
}

public class Closer
{
    public void Close()
    {
        Console.WriteLine("closed");
    }
}

public class ConcreteCloser : Closer, ICloseable 
{
}


class Program
{
    static void Main(string[] args)
    {
        var concrete = new ConcreteCloser();
        concrete.Close();
        Console.ReadKey();
    }
}

So the question is:

The base class does not implement the interface.

Why does the compiler accept the Closer.close() method as implementation of the interface method?

Why is there not a least a warning in both Visual C# 2010 Professional and Eclipse?

For me, C# and Java, are somewhat duck-typed in this case.

Can someone explain me the language considerations behind that please? As both C# and Java do it the same way, there seem to be good reasons for that.

Was it helpful?

Solution

For the question in the title

Interfaces are not Duck Typing.

Nominative Typing:

.. compatibility and equivalence of data types is determined by explicit declarations and/or the name of the types.

This includes Java/C# Classes and Interfaces. All types and relationships between types are defined by name.

Structural Typing:

.. compatibility and equivalence are determined by the type's actual structure or definition, and not by other characteristics such as its name or place of declaration.

This includes Scala Structural Types and C++ Templates.

Duck Typing:

.. object's methods and properties determine the valid semantics.

This includes dynamically typed languages (e.g. Ruby, Python, JavaScript) and C#'s dynamic. I would also tentatively assert that Duck Typing is a subset/untyped form of Structural Typing; it is orthogonal to Nominative Typing.

For the other questions

Why does the compiler accept the Closer.close() method as implementation of the interface method?

Because the Close method is public and has a conforming signature. Since ConcreteCloser inherits from Closer it also obtains all the base classes methods - per Inheritance Subtyping and Liskov Substitution Principle (not all OOP languages use LSP) - and thus conforms-to ICloseable; it then chooses to implement the ICloseable interface by name. I am not sure what warning would be expected here.

If C# was Structurally (or Duck) Typed, then Closer could be used in place of ICloseable, but it cannot; ICloseable c = new Closer() is invalid as Closer is not defined to be nominatively related ICloseable.

For me, C# and Java, are somewhat ducktyped in this case.

No; not unless talking about dynamic in C#. See above.

Can someone explain me the language considerations behind that please? As both C# and Java do it the same way, there seem to be good reasons for that.

This is by language design choice; Interfaces are one method to support Nominative Typing in a Single Inheritance model. Scala (and Ruby) supports Traits; C++ supports Multiple Inheritance. Eiffel supports MI and also breaking LSP at the type level. Go figure - there is no "one right way".

OTHER TIPS

The interface is a contract. That contract states that the type has a method of the given signature. It's not required that the member in question be defined, or re-defined, in the type itself.

This is not related to duck typing. Duck typing means that the members aren't resolved at compile time; they're resolved at runtime. Here the compiler is able to determine that the class implements the method at compile time.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top