面向对象
继承
继承是指在一个类的基础上去构建一个新的类
现实中的继承
子承父业
继承皇位
Java中使用继承
- 将两个子类中相同的代码进行抽取,放到一个新的类中(父类)。
- 让类和类产生关系(继承)
语法格式:class子类名 extends 父类名{}
继承的效果
子类拥有了父类(公有)的属性和方法
Java只能单继承,支持多层继承
继承的注意事项和什么时候使用继承
注意事项:
1. Java 只支持单继承,不支持多继承。
2. 子类只能继承父类所有非私有的成员(成员方法和成员变量)
3. 子类不能继承父类的构造方法,但是可以通过 super(待会儿讲)关键字去访问父类构
造方法。
什么时候使用继承?
继承其实体现的是一种关系:”is a”(是一个),是一种表示特殊与一般的关系。
如果有两个类 A、B。只有他们符合 A 是 B 的一种,或者 B 是 A 的一种,就可以考虑使用继承。
比如,猫(特殊)是一个动物(一般)。关键字 extends 表明正在构造的新类派生于一个存在的类。
示例代码
class A {
public void show1() {}
public void show2() {}
}
class B {
public void show1(){}
public void show3() {}
}
class B extends A {
public void show3() {}
}
//这里 B 不应该继承 A,因为因为 B 本身是没有 show2(),所以继承的关系使得 B 平白无故多出一个方法
继承中成员继承中成员变量的关系
子类中的成员变量和父类中的成员变量名称不一样
可以直接使用
子类中变量名与父类中成员变量名一样
变量寻找方式,遵循就近原则
先在局部位置找变量
如果局部找不到,那么就到当前类成员变量找
如果当前类找不到,那么到父类里面找
再找不到,就报错
注意: 当子类覆盖父类的成员变量时, 每个类使用成员都相当于在前面加了 一个 this 。
示例代码
class Fu {
public int num = 20;
public void showFu(){
System.out.println(num);
}
}
class Zi extends Fu{
public int num2 = 40;
//第二次演示 跟父类同名的变量
public int num = 100;
public void show(){
//第三次演示 定义局部变量 num
int num = 200;
System.out.println(num2);//子类的
//System.out.println(num);//第一次演示是父类的
//System.out.println(num);//第二次演示 100
System.out.println(num);
showFu();
}
}
class ExtendsDemo{
public static void main(String[] args) {
//创建子类对象
Zi z = new Zi();
z.show();
}
}
在类中方法里如果想要调用成员变量,需要使用this关键字
如果子类中有和父类同名的属性,在子类中就可以使用super关键字,调用父类属性
super关键字的使用介绍
- super 关键字:
- 解决使用了继承关系,子类访问父类成员问题 super 使用
- super.成员变量 调用父类的成员变量
- super.(…) 调用父类构造方法
- super.成员方法 调用父类成员方法 相识知识点:this关键字
- this.成员变量 调用本类的成员变量
- this(…) 调用本类的构造方法
- this.成员方法 调用本类的成员方法 this和super的区别
- this代表的是本类对象的引用
- super代表的是父类存储空间的标识(可以理解成父类的引用,可以操作父类的成员)
示例代码
class Fu{
int num = 10;
}
class Zi extends Fu{
int num = 20;
public void show(){
int num = 30;
System.out.println(num);
System.out.println(this.num);//访问子类中的成员变量
System.out.println(super.num);//访问父类中的成员变量
}
}
class ExtendsDemo5{
public static void main(String[] args) {
//创建对象
Zi z = new Zi();
z.show();
}
}
继承中构造方法的关系
案例演示
子类中所有的构造方法默认都会访问父类中空参数的构造方法为什么呢?
因为子类会继承父类中的数据,可能还会使用父类的数据。 所以,子类初始化之前,一定要先完成父类数据的初始化。
其实:
每一个构造方法的第一条语句默认都是:super()
如果这个类没有去继承其他的类,默认继承 Object 类,每个类都使用 Object 作为超类
继承中构造方法的注意事项
父类添加有参构造方法等
父类没有无参构造方法,子类怎么办?
在父类中添加一个无参的构造方法
子类通过 super去显示调用父类其他的带参的构造方法
子类通过 this去调用本类的其他构造方法
本类其他构造必须首先访问了父类构造
代码示例
class Fu{
/*
public Fu(){
System.out.println("父类无参构造!");
}
*/
public Fu(String name){
System.out.println("父类带参构造!");
}
}
class Zi extends Fu{
public Zi(){
//super();
super("张三");
System.out.println("子类无参构造!");
}
public Zi(String name){
//super();
//super("aa");
this();
System.out.println("子类带参构造!");
}
}
class ExtendsDemo7{
public static void main(String[] args) {
//创建对象
//Zi z = new Zi();
Zi z2 = new Zi("赵六");
}
}
方法重写概述及其应用
什么是方法重写
子类中出现了和父类中一模一样的方法声明(方法名,参数列表,返回值类型),也被称为方法覆盖,方法复写。
方法重写的应用:
当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法。
这样,即沿袭了父类的功能,又定义了子类特有的内容。
案例演示
//定义一个手机类。
//通过研究,我发明了一个新手机,这个手机的作用是在打完电话后,可以听天气预报。
class Phone{
public void call(){
System.out.println("打电话功能");
}
public void sendMess(){
System.out.println("发短信");
}
public void playGame(){
System.out.println("消消乐");
}
}
class BoomCronPhone extends Phone{
public void call(){
//System.out.println("打电话功能");
super.call();//这句话体现了继承的魅力
System.out.println("需要什么口味的爆米花就给你爆什么味的!");
}
}
class ExtendsDemo9{
public static void main(String[] args) {
//Son s = new Son();
//s.show();
BoomCronPhone bcp = new BoomCronPhone();
bcp.call();
bcp.sendMess();
bcp.playGame();
}
}
方法重写的注意事项
方法重写注意事项
父类中私有方法不能被重写
因为父类私有方法子类根本就无法继承
子类重写父类方法时,访问权限不能更低
最好就一致
父类静态方法,子类也必须通过静态方法进行重写
其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态
中会讲解
子类重写父类方法的时候,最好声明一模一样。
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
vivo v= new vivo();
v.call();
v.photo();
hw h = new hw();
h.call();
h.photo();
}
}
class Phone{
public void call(){
System.out.println("打电话");
}
public void photo(){
System.out.println("拍照");
}
}
class vivo extends Phone{
public void photo(){
System.out.println("拍照并自动美颜");
}
}
class hw extends Phone{
public void photo(){
System.out.println("双摄拍照,随时虚化");
}
}