为什么Java只接受具有相同返回类型的重写基类方法?

时间:2017-09-14 10:48:09

标签: java c#

我在C#中的背景。我想知道为什么Java重写的基类方法需要相同的返回类型,即使我们将重写的返回类型更改为基类类型它会引发错误。任何人都可以让我知道这个的原因吗?请从下面找到代码段。

public class ListIterator
     extends Test // Test is base for ListIterator
{
}

class Collection
{
    public ListIterator iterator() throws Exception {
        return new ListIterator();
    }
}


class Child 
    extends Collection
{
   //Here the return type “Test” is the base for ListIterator, but still it 
   //throws error to mark the return type as ListIterator. If we comment the 
   //extended base class "Collection" it works as expected.

    public Test iterator() throws Exception {
        return new ListIterator();
    }
}

2 个答案:

答案 0 :(得分:5)

首先,不,这在C#中不起作用 - 当你实际上覆盖该方法时。 (如果你使用new它会工作,但是你没有覆盖。)C#比Java更严格,因为返回类型必须完全匹配...而Java允许你返回更多特定的类型,只是不是更一般的类型。例如,这很好:

public class Base {
    public Object getFoo() {
        ...
    }
}

public class Child extends Base {
    @Override public String getFoo() {
        ...
    }
}

......但你正试图做相反的事情。

要说明为什么这很危险,请假设您已将Child.iterator()方法实施更改为return new Test();。然后想象有人写道:

Collection collection = new Child();
ListIterator iterator = collection.iterator();

所有内容看起来都是完全类型安全的,因为Collection.iterator()被声明为返回ListIterator - 但返回的值既不是null也不是对ListIterator的引用。

所以基本上,答案是“Java正在保护你不要在脚下射击自己。这是一件好事。”

答案 1 :(得分:1)

子类型必须具有与其超类型相同或更高的功能。形式上,这被称为Here's

如果ListIterator延伸Test,那么ListIterator可能比Test更有能力,而且可能是Child,否则就没有意义。

如果Collection延伸Child,则Collection不得通过从其中一种方法返回功能较弱的类型来降低{{1}}的功能。

如果这在C#中有效,那么C#就会被破坏。