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++模板。从技术上讲,它是在编译时执行验证,但它不是验证模板类型是否总是给定类型,只是验证它具有给定的操作。感谢您全面的回答!