多态性和接口

Posted

技术标签:

【中文标题】多态性和接口【英文标题】:polymorphism and interfaces 【发布时间】:2011-02-20 12:38:17 【问题描述】:

如果我有两个类 x 和 y,都扩展类 w。和 x 实现接口 z。如果我有方法 doSomething(w object) 和 doSomething(x object),如果我调用 doSomething(x) 会发生什么?

编辑: 我在java上实现这个,更具体地说是在android上。 我问这个是因为一些实现特定接口的类在调用 doSomething() 时大多做同样的事情。但有一些特殊情况我想单独指出。

【问题讨论】:

你能说得更具体点吗?你是指钻石问题还是别的什么? 这可能取决于所讨论的编程语言,但通常编译器会选择具有最佳拟合参数类型的方法,在这种情况下采用x object 你为什么不试试呢?没有什么不好的事情会发生在你身上。 :) +1:这是一个很好的问题,我想说这取决于语言。 // 鉴于我不知道您指的是哪种语言,您为什么不在您选择的语言中尝试这个场景,并尝试调用 w 和 x 独有的方法? 【参考方案1】:

这取决于您使用的语言。

例如,在 C# 中,它会使用 doSomething(x object) 而不是 doSomething(w object)。

但是,如果你将它转换为 w,那么它会像这样使用 doSomething(w object):

doSomething((w) someObjectOfX);

doSomething(someObjectOfX as w);

【讨论】:

【参考方案2】:

假设你有

w object1 = new x();
x object2 = new x();

传递 object1 将执行 doSomething(w object) 并传递 object2 doSomething(x object)

P.S: 当然取决于语言(谈到 C#)

P.P.S:添加参数名称以使其更清晰

【讨论】:

-1:这个答案假设 doSomething(w) 和 doSomething(x) 不是 both 在 x 上实现的。 w 和 x 是类型,而不是变量。现在应该很清楚了。 :) @jim G:如果它们都在 x 上实现会怎样? @mixm:对不起,我错了。当然它也可以(在 C# 上)!我建议你谷歌“多态”、“覆盖方法”、“虚拟方法”、“重载方法”、“隐藏方法”。在那之后,您应该成为该主题的专家;)【参考方案3】:

在 C# 中,编译器将根据变量的声明类型而不是存储在其中的实际类型来选择正确的方法。

注意,下面的代码将W 声明为一个类,并构造它的一个实例。如果将W 设为接口,并删除其声明和构造,则xy 的行为将与下面的程序相同,在这种情况下W 的接口或类无关紧要。

让我告诉你区别:

using System;

namespace SO2851194

    class W  
    class X : W  
    class Y : W  

    class Program
    
        static void Main()
        
            W w = new W();
            X x = new X();
            Y y = new Y();

            doSomething(w);
            doSomething(x);
            doSomething(y);
        

        static void doSomething(W w)
        
            Console.Out.WriteLine("w");
        

        static void doSomething(X x)
        
            Console.Out.WriteLine("x");
        
    

这里我声明了三个变量,类型为WXY,并调用doSomething,一一传递这三个变量。这个程序的输出是:

w
x
w

正如预期的那样,编译器将选择具有最佳拟合参数类型的方法,并且在 x 变量的情况下,它有一个可以采用 X 类型的对象的方法。

但是,由于类继承,我们可以更改变量的声明,但保持对象类型的构造,因此更改代码如下:

W w = new W();
W x = new X();   // Notice, changed variable type to W
W y = new Y();   // but keep constructing X and Y

现在输出:

w
w
w

因此,x 变量包含 X 类型的对象这一事实并未考虑在内,编译器从变量类型而非其内容中选择了方法。

在 C# 4.0 中,您现在拥有 dynamic 类型,因此再次将代码更改为:

dynamic w = new W();
dynamic x = new X();
dynamic y = new Y();

再次输出:

w
x
w

因为现在编译器将选择任何方法推迟到运行时,并且在运行时,它会看到名为x 的变量实际上包含X 类型的对象,然后选择具有最佳拟合参数类型的方法。

【讨论】:

【参考方案4】:

你不能有两种不同的方法具有相同的签名。它的代码模棱两可,编译器不会编译,解释器会抛出错误。

【讨论】:

签名不同。第一个是 x 类,第二个是 y 类。这是一个完全合法的问题。

以上是关于多态性和接口的主要内容,如果未能解决你的问题,请参考以下文章

多态性和接口

关于 Java 接口和多态性

C#多态性学习,虚方法抽象方法接口等用法举例

JAVA 作业 实验名称:接口,继承与多态

多态&接口

php学习笔记 面向对象中[接口]与[多态性]的应用