Java随堂笔记课【八】:重载、继承、重写

重载 overload

在面向过程的编程语言中,函数名不能重复,一个优秀的函数名在用过一次以后,不能再复用,是一种浪费。程序员不得不去寻找替代名字。
在面向对象的编程中,语言考虑到这些问题,支持方法名复用,只要参数数量或者参数类型不同就可以了。这种做法叫做重载(override)。

比如 strA.concat(strB) 等价于 strA += strB就是重载运算符的一种,只不过它重载的不是名字而是运算符,比较特殊罢了。

重载的实现条件:

  1. 参数数量不同,直接构成重载。
  2. 参数数量相同,但是对应位置上的参数只要有一个参数数据类型不同,也能构成重载。
  3. 参数名不构成重载条件。(在编译的时候,只保留重载函数声明的变量内型)
  4. 返回值不构成重载条件。
  5. 访问修饰符以及static,final等符号也都不构成是否重载的条件。
public int add(int x,int y){
    return x + y;
}

//正确。1:参数数量不同,直接构成重载。
public int add(int x,int y,int z){
    return x + y + z;
}
//正确。2:参数数量相同,但是对应位置上的参数只要有一个参数数据类型不同(本例int和float不同),也能构成重载。
public int add(int x, float y){
    return x + y;
}

//错误!3:参数名(x,y和x2,y2不同)不构成重载条件!
//编译的时候只保留一句(public int add(int x,int y))。
public int add(int x2,int y2){
    return x2 + y2;
}

//错误!4:返回值(x+y和5不同)不构成重载条件!
public int add(int x, int y){
    return 5;
}

继承 extends

java中,当类A继承类B,代码写法如下:

public class A extends B

类A继承了类B所有的可以继承的变量


常见的叫法

父类=基类=超类
子类=派生类
文档里经常有这五种叫法,其实就是这两个意思。


“俄罗斯套娃”模式

关于继承,在内存的堆中,我们可以画出概念图,用来理解继承是怎么在内存中运作的。
(注:这并不是内存布局,只是概念图,实际在内存中的地址分配不是这样的)

这里写图片描述

在图中,A类继承B类,B类继承object类。A类和B类都有各自的方法和属性可以用。
这种概念确实很像“俄罗斯套娃”。


object类

在Java里,所有类都必须继承自object类。object类是java中自带的一个基础类,有作为一个类必须拥有的方法。

考虑到使用太频繁,object内部代码几乎都是用native编写的。

不过,子类如果继承父类,就没有必要继承object类了。因为父类已经继承。具体可以看上边的那个图。


继承类的调用和构造

还是看之前的图。

在调用的时候,从外向内一层一层找,找到就开始执行
比如在堆栈中,如果A a发出了a.goToWork()的指令。那么,程序就会先在A类的所有方法中找一下,是否存在goToWork,显然找不到。于是,开始进入父类继续在父类的所有方法中寻找。这次可以在B类的范围中成功找到goToWork。这才开始执行函数相关操作。

在构造到时候和调用相反,从内向外一层一层构建。先父亲再儿子的模式理解起来并不难。


继承类在内存中变量的指向问题

假设我们在堆栈中有一个类B b,一个类Object obj,一个类A a,那么如果他们指向响应的堆栈空间,将会如下图展示:

这里写图片描述

其中,标配指向表示指向了自己本身的类。比如A指向了a,B指向了b。正好对应完整的一部分。
同时,父类指向子类是可以的。比如B b指向A instance。但是,父类在指向子类的同时会将其视作父类,子类部分无法调用。也就是说这种情况下可以用的只有B instance里面的那一部分,外边的是不可以的。这种现象叫萎缩效应。
另外,子类指向父类是不可以的。比如A a指向B instance。子类会尝试将其膨胀为父类,引发不可知的错误。


重写 override

在子类中拥有与父类同名的方法,称之为重写。比如,我们在子类和父类中各添加一个goHome()方法。
作为一个子类,重写的方法有两种,改良性重写和颠覆性重写。


改良型重写和颠覆性重写

改良型重写的写法如下:

/**
 * 这段代码是在子类A中存在的方法。
 * B类已经有了一个同名的goHome()方法。
 * 现在将会在A中对其实现改良性重写。
 */
void goHome(){
    //继承父类。
    super();
    //执行子类个性化指令。
    xxxxxxxxxxxxxxxx`
;
    ...
}

颠覆型重写的写法如下:

/**
 * 这段代码是在子类A中存在的方法。
 * B类已经有了一个同名的goHome()方法。
 * 现在将会在A中对其实现颠覆性重写。
 */
void goHome(){
    //不再继承父类,直接执行子类个性化指令。
    xxxxxxxxxxxxxxxxx;
    ...
}

看到了吧,并不复杂。其实唯一区别就在于是否把父类执行的语句用super传承下来。
但是有一点,在A类中如果想调用父类B的同名方法,必须用Super识别之。比如,在A类中执行Super.goHome()。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值