java里,为啥子类不可以有 和父类 同名不同返回类型 的方法?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java里,为啥子类不可以有 和父类 同名不同返回类型 的方法?相关的知识,希望对你有一定的参考价值。

比如父类有这个方法:public int aa()retrun 1;
子类就不能有这个方法了:public long aa()return 2;

首先要看该方法的使用范围,
如果是private,那么这样定义是没有问题的。
如果不是private的。我们知道,子类是可以访问父类的非private方法。这样的话,如果子类有和父类同名不同返回类型的方法,就相当于在一个类中有两个同名不同返回类型的方法,这在java中犯了二异性的错误,是不允许的。
参考技术A Java的重写和重载是两种在Java中经常提到的两组概念,它们在各个方面都有着很大的不同,下面详细介绍你要了解的区别。

Java的多态机制

即重写,重写主要用于子类和父类之间,在父类中定义了一个方法,同时在子类中对这个方法进行重写,实现子类行为的特殊化,例如:
class Animal

void eat() System.out.print("animal eat");



class Tiger extends Animal

void eat()System.out.print("Tiget eat");



子类中的eat方法即对父类的eat方法实现了重写,重写最常见的例子就是下面的声明:

Animal some=new Tiger();

关于重写,遵循以下的规则:

(1)重写方法必须和被重写方法具有相同的参数列表,返回类型必须和被重写方法的返回类型相同或者是返回类型的子类型。

(2)重写方法的访问控制修饰符不能比被重写方法更严格(比如一个在父类中声明为public的方法重写成一个protected的方法)。

(3)只有实例方法才能被重写,超类中的final方法不能被重写。

(4)重写方法不能抛出新的检查异常,或者是抛出比被重写方法声明的检查异常更广泛的检查异常。

(5)注意一种特殊情况:如果超类的方法版本中声明了检查异常,但重写的子类方法中没有声明,这时如果使用多态的方式进行调用,那么编译器认为你调用的是声明了异常的方法。

(6)尽管多态是在编译时确定对象的类型,但在编译时,还是根据父类的方法声明进行程序检查。因此,如果子类中定义的方法,在父类中没有定义,则会出项编译错误。

Java的重载机制:
重载的实质:在一个类中使用签名相同的多个方法。

按照范围,可以将重载分为在一个类中重载,和在子类和父类中重载。现分别解释如下:

1.在一个类中定义多个具有相同签名的方法,这些方法必须具有不同的参数列表,比如一个类的构造函数。

2.在父类和子类中,子类由于继承而拥有了父类的某些方法,此时在子类再定义具有相同签名的方法(必须具有不同的参数列表),这个地方很容易和重写相混淆,因此千万注意。

重载的规则主要记住亮点:
一是方法的参数列表必须改变,包括参数的类型,参数的个数多少,参数顺序。

二是重载对返回类型,访问修饰符,异常声明没有任何限制,可以作任意的修改。实质上,重载只是创建了一个方法而已,特殊的地方在于方法的名字。

注意下面的一种情况:(重写和重载的混合)

class UseAnimal

void doStuff(Animal sa)

void doStuff(Tiger sa)

public static void main(String[] args)

UseAnimal ua=new UseAnimal();

Animal an=new Tiger();

ua.duStuff(an);





此时,调用的方法doStuff的Animal版本,因为调用重载方法是在编译时决定的,an的声明类型是Animal。所以调用Animal版本。

始终注意一点:重载的判断始终是在编译时决定
参考技术B 因为子类中方法和父类方法同名,系统以为是子类重写父类的方法。

java的方法重写
1、在子类中可以根据需要对从基类中继承来的方法进行重写。
2、重写的方法和被重写的方法必须具有相同方法名称、参数列表和返回类型。
3、重写方法不能使用比被重写的方法更严格的访问权限。
参考技术C 涉及到方法的覆盖,"父",就是老子,老子才int,儿子却long,比老子还大,这是不行的,总之一定要比老子小或者平级也行

java super关键字

  我们已经知道,如果子类中定义的成员变量和父类中的成员变量同名时,则父类中的成员变量不能被继承,此时称子类的成员变量隐藏了父类的成员变量。

当子类中定义了一个方法,并且这个方法的名字,返回类型,参数个数以及类型和父类的某个方法完全相同时,父类的这个方法将被隐藏(重写),既不能被子

类继承下来。如果我们在子类中想使用被子类隐藏的父类的成员变量或方法就可以使用关键字super。因此,super是用在子类中,目的是访问直接父类中被屏蔽

的成员,注意是直接父类(就是类之上最近的超类)。

1  使用super调用父类的构造方法

        子类不继承父类的构造方法。因此,子类如果想使用父类的构造方法,必须在子类的构造方法中使用,并且必须使用关键字super来表示。而且super必须是

子类构造方法中的头一条语句(也就是说父类必须自己负责初始化她自己的状态而不是让子类来做)。

       需要注意的是:如果在子类的构造方法中,没有显示地使用super关键字调用父类的某个构造方法,那么默认地有 super();语句,即调用父类的不带参数的构

造方法。如果父类没有提供不带参数的构造方法,就会出现错误。特别注意:当存在有参构造器时,无参构造器就不存在了,必须显示的声明空构造器。

2  使用super操作被隐藏的成员变量和方法

       如果我们在子类中想使用被子类隐藏了的父类的成员变量或方法就可以使用关键字super。比如super.x,super.play(),就是被子类隐藏的父类的成员变量x和方法play()。

关键字super和继承一起建立类和它的父类的紧密联系。例如,当我们要调用一个实例方法时,如果实例本身并没有定义该方法,那我们自然地会得到它的父类中定义的同名方法。

尽管会因为方法的覆盖或者使用定义与父类一样的实例或类变量(叫做“隐藏”)而失去这种访问的权力。这就是为什么要使用super这个关键字,它显式地指出子类可以直接访问父类中的某些部分,

尽管有时这种访问会因为种种原因被屏蔽了的方法在其父类中的原始代码。

 关键字Super在构造函数的使用中是非常重要的,和方法不同,构造函数是不被继承的;因此super是访问父类中构造函数的惟一途径。在子类的构造函数 中,

使用super( )和适当的参数表可以触发对父类构造函数的一个调用,如果父类没有相应的构造函数,编译器会报错,这就是每个实例实现的初始化的过程链。

实例先把自己作为一个Object实例进行初始化,然后从它的直接子类开始按照继承链依次调用构造函数直到最后将与当前类直接相关的内容初始化完毕。

子类的构造函数如果要引用super的话,必须把super放在函数的首位,不然会出现这样的报错:
   Checket.java:10: call to super must be first statement in constructor

那么在类中用super调用父类构造函数时,为什么调用语句必须是子类的第一条语句?

答案:如果想用super继承父类构造的方法,但是没有放在第一行的话,那么在super之前的语句,肯定是为了满足自己想要完成某些行为的语句,但是又用了super继承父类的构造方法。那么以前所做的修改就都回到以前了,就是说又成了父类的构造方法了

下面总结一下super的用法:
       第一、在子类构造方法中要调用父类的构造方法,用“super(参数列表)”的方式调用,参数不是必须的。

    同时还要注意的一点是:“super(参数列表)”这条语句只能用在子类构造方法体中的第一行。
       第二、当子类方法中的局部变量或者子类的成员变量与父类成员变量同名时,也就是子类局部变量覆盖父类成员变量时,

    用“super.成员变量名”来引用父类成员变量。当然,如果父类的成员变量没有被覆盖,也可以用“super.成员变量名”来引用父类成员变量,不过这是不必要的。
       第三、当子类的成员方法覆盖了父类的成员方法时,也就是子类和父类有完全相同的方法定义(但方法体可以不同),此时,用“super.方法名(参数列表)”的方式访问父类的方法。
       第四、super关键字只能用在类体中非静态部分,比如构造函数与成员方法中,若在main函数中调用或静态方法中编译会出错,报Cannot use super in a static context的错误!

注意:父类的属性和方法必须是哪些protected或者public等可以让子类访问的属性或者方法。






以上是关于java里,为啥子类不可以有 和父类 同名不同返回类型 的方法?的主要内容,如果未能解决你的问题,请参考以下文章

java函数重写/重载

什么是类的继承性?Java中子类和父类有什么关系?

java变量和方法的覆盖和隐藏(翻译自Java Tutorials)

java中方法的重载和覆盖分别要满足的条件

C++ 当子类的方法和父类的方法重名时...

继承,虚继承机制