[英]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 . 这里编译器能够确定该类在编译时实现该方法。
Interfaces are not Duck Typing. 接口不是Duck 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 . 类型之间的所有类型和关系都由名称定义。
.. 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正交。
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.