主页

Java继承与多态

Java继承与多态

基本概念

被继承的类称为基类父类超类,而新的类被称为派生类子类

一般把基类和派生类实例的集合称作类继承层次结构

Java中的类只支持单一继承(即一个类只有一个父类)。

在需要多重继承的场合,可以使用接口机制来实现。

 

子类会自动继承父类中的非private成员(是否继承静态成员??)。但不会继承父类中的构造方法。

继承是可以传递的,如 类B继承类A,类C又继承类B,类C相当于拥有了类A中的可继承的那些成员,这些继承而来的成员就好像在类C中定义的一样。

 

属性隐藏和方法覆盖

当子类的成员属性和父类的成员属性同名时(和属性的类型无关),称为父类的成员属性(变量)被隐藏。

当子类的成员方法和父类的成员方法同名时(和属性的类型无关),称为父类的成员方法(行为)被覆盖。

子类中的同名属性允许与父类的同名属性在 访问权限、数据类型、常/变量(final)、实例/静态 等方面完全不同,最终以子类的属性特性为准。

所以,对于属性,只要同名就能隐藏,没有任何限制。

 

覆盖必须满足两个条件: 1. 方法名称必须相同   2. 返回值类型必须相同,方法的参数必须完全相同,包括参数的个数、类型、顺序。

如果只满足第1条而不满足第二条,则是方法的重载。

覆盖时,子类方法的访问权限必须不比父类中同名方法更严格,否则报错(注意是报错,而不是方法重写)。 例如 父中为public ,则子类中覆盖时也必须是public。

如果父类中的方法是一个final方法,则子类对其进行覆盖会报错。如果父类中的方法不是final方法,在子类中可以覆盖为一个final方法。

不允许父类方法和子类方法在覆盖时,static 修饰符发生变化,否则报错(注意是报错,而不是方法重写)。

覆盖也是多态的表现。覆盖需要在运行代码的时候确定调用的是哪个方法。

 

继承中的构造方法

所有的构造函数都不会被继承。

假设类B继承类A:

1. 如果类B中一个构造方法也没有显示定义,则系统会自动给类B添加一个不带参数的构造方法。

2. 当调用B中的某个构造方法B(...)时(创建B对象时),必然会调用其父类A的某个构造方法来创建A类对象。

     如果 B(...)中没有显示调用  super(...);this(...); , 则自动在方法体的行首添加 super(); (而不是报错)。

     如果显示调用了,则什么也不做。注意,如果调用了this(....),就可能在另一个构造函数中调用了super(...)

     其中 super 代表父类的构造函数, this 代表本类的构造函数。

 

super

当super作为方法调用时:

1. 只能在构造方法中调用 super(....)

2. super只能是构造方法中的第一条语句。

3. 一个构造方法中,最多只能有一个super方法调用。  

使用 super.父类成员名  可以引用或修改父类成员的属性值 或 调用父类的成员方法。

 

继承的内部处理

假设类B继承类A:

当创建B类对象时,同时也会新创建一个A类对象,再新创建A的父类, .... , 一直到创建 Object类的对象。 这样就形成一个链条,称为原型链作用域链

当 A对象.成员  时,会从A类对象开始,在原型链上依次查找,直到找到第一个同名成员。

原型链上的所有对象,均是完整的对象,每个对象对应类中定义的所有成员都存在于这个对象上,只是这些成员是否对子类可见或不可见而已。

 

多态:重载

多态是指一个名字拥有多种语义。

一个类中,允许多个方法拥有相同的名字,但参数列表必须不一样,能在调用时根据实参列表推算出应该调用哪个方法,这就是重载。

重载的一组方法必须满足:  1. 方法名相同   2. 参数个数 或 对应位置上的参数类型 不同

不允许参数列表完全相同,仅返回值类型不同的情况出现,否则报错。

重载的过程中区分调用哪个方法是在编译时确定的,所以重载是一种静态绑定的技术。

构造方法也可以重载。

两个方法是否是重载关系,只看规则1和2。不关注  前面的修饰符(也就是说,不管前面出现什么样的修饰符,都可以重载,也不影响重载)。

重载发生在同个类中,或者父类与子类中。

 

运行时多态

当方法被调用时,系统根据对象本身所属的类来确定调用哪个方法,这种技术称为后期(动态)绑定。

设 类A是类B的父类,在类B中隐藏了实例属性 realHideA,隐藏了静态属性 staticHideA,覆盖了实例方法 realCoverFn(),覆盖了静态方法 staticCoverFn()。

当有代码:  A test = new B();   或者   B b = new B(); A test = b;  时

test.realHideA  test.staticHideA  test.staticCoverFn()  访问的属性和方法是类A中的,而  test.realCoverFn() 则是访问的类B中的方法。 

也就是实例属性、静态属性、静态方法,在访问时,是根据这个变量的类型来确定的究竟访问的是哪个类上的。

综上,只有实例方法被覆盖时,才会表现出运行时多态。

 

posted @   平凡人就做平凡事  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示