简体   繁体   English

C#和Java是鸭子吗?

[英]Is C# and Java duck-typed?

Today we had a strange happening with a close() method. 今天我们用close()方法发生了奇怪的事情。

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? 为什么编译器接受Closer.close()方法作为接口方法的实现?

Why is there not a least a warning in both Visual C# 2010 Professional and Eclipse? 为什么在Visual C#2010 Professional和Eclipse中都没有至少一个警告?

For me, C# and Java, are somewhat duck-typed in this case. 对我来说,C#和Java在这种情况下有点类型。

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. 由于C#和Java都以同样的方式执行,因此似乎有充分的理由。

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 . 这里编译器能够确定该类在编译时实现该方法。

For the question in the title 对于标题中的问题

Interfaces are not Duck Typing. 接口不是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. 这包括Java / C#类和接口。 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. 这包括Scala结构类型和C ++模板。

Duck Typing : 鸭子打字

.. object's methods and properties determine the valid semantics . ..对象的方法和属性决定了有效的语义

This includes dynamically typed languages (eg Ruby, Python, JavaScript) and C#'s dynamic . 这包括动态类型语言(例如Ruby,Python,JavaScript)和C#的dynamic I would also tentatively assert that Duck Typing is a subset/untyped form of Structural Typing; 我还试探性地断言Duck Typing是结构类型的子集/无类型形式; it is orthogonal to Nominative Typing. 它与Nominative Typing正交。

For the other questions 对于其他问题

Why does the compiler accept the Closer.close() method as implementation of the interface method? 为什么编译器接受Closer.close()方法作为接口方法的实现?

Because the Close method is public and has a conforming signature. 因为Close方法是公共的并且具有符合标记的签名。 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 ; 由于ConcreteCloser继承自Closer,它还获得所有基类方法 - 每个继承子类型Liskov替换原则 (并非所有OOP语言都使用LSP) - 因此符合ICloseable ; it then chooses to implement the ICloseable interface by name . 然后它选择按名称实现ICloseable接口。 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; 如果C#是结构性(或鸭子)类型,则可以使用Closer代替ICloseable,但它不能; ICloseable c = new Closer() is invalid as Closer is not defined to be nominatively related ICloseable. ICloseable c = new Closer()是无效的,因为更紧密没有定义被nominatively相关ICloseable。

For me, C# and Java, are somewhat ducktyped in this case. 对我来说,在这种情况下,C#和Java在某种程度上是假的。

No; 没有; not unless talking about dynamic in C#. 除非在C#中谈论dynamic 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. 由于C#和Java都以同样的方式执行,因此似乎有充分的理由。

This is by language design choice ; 这是语言设计的选择 ; Interfaces are one method to support Nominative Typing in a Single Inheritance model. 接口是支持单一继承模型中的命名类型的一种方法。 Scala (and Ruby) supports Traits; Scala(和Ruby)支持Traits; C++ supports Multiple Inheritance. C ++支持多重继承。 Eiffel supports MI and also breaking LSP at the type level. Eiffel支持MI并且还在类型级别破坏LSP。 Go figure - there is no "one right way". 去图 - 没有“正确的方法”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM