C#和javaduck是类型化的吗?

C#和javaduck是类型化的吗?,c#,java,inheritance,interface,duck-typing,C#,Java,Inheritance,Interface,Duck Typing,今天我们在close()方法中遇到了一个奇怪的情况 以下是有疑问的代码: interface ICloseable { void Close(); } public class Closer { public void Close() { Console.WriteLine("closed"); } } public class ConcreteCloser : Closer, ICloseable { } class Program {

今天我们在
close()
方法中遇到了一个奇怪的情况

以下是有疑问的代码:

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();
    }
}
因此,问题是:

基类不实现接口

为什么编译器接受
Closer.close()
方法作为实现 接口方法的定义?

为什么Visual C#2010 Professional中没有一个警告 日蚀呢

对我来说,C#和Java在这种情况下有点像鸭子

有人能给我解释一下这背后的语言考虑吗?
由于C#和Java都是以同样的方式实现的,所以这似乎有很好的理由。

接口是一个契约。该合同规定该类型具有给定签名的方法。不需要在类型本身中定义或重新定义有问题的成员

这与duck类型无关。Duck类型表示在编译时不解析成员;它们在运行时被解析。在这里,编译器能够确定类在编译时实现了该方法。

关于标题中的问题 接口不是Duck类型

:

。。数据类型的兼容性和等效性由显式声明和/或类型名称决定

这包括Java/C类和接口。所有类型和类型之间的关系都由名称定义

:

。。兼容性和等价性是由类型的实际结构或定义决定的,而不是由其名称或声明位置等其他特征决定的

这包括C++模板。 :

。。对象的方法和属性决定了有效的语义

这包括动态类型语言(如Ruby、Python、JavaScript)和C#的
dynamic
。我还暂时断言Duck类型是结构类型的子集/非类型形式;它与主格类型是正交的

至于其他问题 为什么编译器接受Closer.close()方法作为接口方法的实现

因为Close方法是公共的,并且具有一致性签名。由于ConcreteCloser继承自Closer,因此它还获得了所有基类方法-per和(并非所有OOP语言都使用LSP)-因此符合ICloseable;然后,它选择按名称实现ICloseable接口。我不确定这里会有什么样的警告

如果C#是结构(或Duck)类型,那么Closer可以代替ICloseable,但它不能
ICloseable c=new Closer()
无效,因为Closer未定义为与ICloseable命名相关

对我来说,C#和Java在这种情况下有点像ducktyped

没有;除非在C#中谈论
动态
。见上文

有人能给我解释一下这背后的语言考虑吗?由于C#和Java都是以同样的方式进行的,因此似乎有很好的理由


这是由语言设计选择的;接口是在单个继承模型中支持命名类型的一种方法。Scala(和Ruby)支持Traits;C++支持多重继承。Eiffel支持MI,并在类型级别打破LSP。算了吧——没有“一条正确的道路”。

对离题的投票是否接近?为什么?作为旁注:.net还具有“动态”功能,它允许基本上是duck类型。然而,这与接口(本例)完全无关。@nawfal你介意建议一个更好的接口吗?这只是我试图传达我的“错误”之处。我不认为Duck类型化意味着成员在编译时不会被解析,尽管我只在动态类型化语言中见过这个术语,我不能在Java/C#中提供一个“术语用法的反例”。@user2246674是的,也许有更好的说法。这实际上不是定义的正式部分,只是这个术语在某些上下文中的常见含义。是的,我想这就是我挂断电话的地方。在实际使用中,这是有道理的,但是。。难道不是这样吗?可能只是可接受的名称根据其他含义而改变(例如Scala中的结构类型)。谢谢您的回答!我理解这里发生了什么,但我真的想知道为什么会这样处理。我想这也很容易出错。@user2246674是的,它可以。想到的最好例子是C++模板。从技术上讲,它是在编译时执行验证,但它不是验证模板类型是否总是给定类型,只是验证它具有给定的操作。感谢您全面的回答!