Java基础35 面向对象三大特征之继承

● 继承基本介绍

继承可以解决代码复用,让我们的编程更加靠近人类思维,当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends来声明继承父类即可。

● 继承的基本语法

class 子类 extends父类{
     代码块
}

this()调用本类构造器
super()调用父类构造器

1)子类会自动拥有父类定义的属性和方法。
2)父类又叫基类,超类(Object)。
3)子类又叫派生类。

继承的好处:

1)代码的复用性提高
2)代码的扩展性和维护性提高

● 继承的深入细节

  1. this()调用本类构造器
    super()调用父类构造器
  2. 子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问,但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问。
  3. 子类必须调用父类的构造器,完成父类的初始化。
  4. 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过。
  5. 如果希望指定去调用父类某个构造器,则显示的调用一下:super(参数列表)
  6. super在使用时,必须放在构造器第一行(super只能在构造器中使用)
  7. super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器中。
  8. java所有类都是Object类的子类,Object是所有类的超类(基类)。
  9. 父类构造器的调用不限于直接父类!将一直往上溯直到Object类(顶级父类)
  10. 子类最多继承一个父类(指直接继承),即java中是单继承机制

例如:如何让A类继承B类和C类?【A继承B,B继承C】

  1. 不能滥用继承,子类和父类之间必须满足is-a的逻辑关系。
Person is a Music?
Person Music
Music extends Person //不合理

Animal
Cat extends Animal // 合理

● 继承的本质分析(☆)

以下列代码为例:

public class ExtendsTheory{
	public static void main(String[] args){
		Son son = new Son(); 
		//按照查找关系来返回信息
		//(1) 先看子类是否有该属性
		//(2)如果子类有这个属性,并且可以访问,则返回信息
		//(3)如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回该信息)
		//(4)如果父类没有就按照(3)的规则,继续找上级父类,直到Object
		System.out.println(son.name); //son有name属性,返回:大头儿子
		System.out.println(son.age); //son没有age属性,向上级寻找,而父类中有age属性,则返回父类的age: 39。
		System.out.println(son.hobby);//son与father都没有hobby属性,而爷类有,就返回爷类的信息: 旅游
	}
}
class GrandPaP{ //爷类
	String name = "大头爷爷";
	String hobby = "旅游";
}
class Father extends GrandPa{ //父类
	String name = "大头爸爸";
	int age = 39;
}
class Son extends Father{
	String name = "大头儿子";
}

注意:继承最终输出是按照查找关系来返回信息

	(1) 先看子类是否有该属性
	(2)如果子类有这个属性,并且可以访问,则返回信息
	(3)如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回该信息)
	(4)如果父类没有就按照(3)的规则,继续找上级父类,直到Object

以上面的例子,画出继承JVM内存布局

在这里插入图片描述

● 继承练习

练习1

以下代码在main中,执行B b = new B(); 会输出什么?

class A{
	A(){
		System.out.println("a");
	}
	A(String name){
		System.out.println("a name");
	}
}
class B extends A{
	B(){
		this("abc");
		System.out.println("b");
	}
	B(String name){
		System.out.println("b name");
	}
}

注意:
B(String name){}中其实隐藏了一个super();
所以最终输出答案为:a,b name,b

练习2

以下代码输出结果是什么?

class A{
	public A(){
		System.out.println("我是A类");
	}
}

class B extends A{
	public B(){
		System.out.println("我是B类的无参构造");
	}
	public B(String name){
		System.out.println(name + "我是B类的有参构造");
	}
}

class C extends B{
	public C(){
		this("hello");
		System.out.println("我是C类的无参构造");
	}
	public C(String name){
		System.out.println("我是C类的有参构造");
	}
}

分析:
(1)从class C开始,【进入到 C的无参构造器】
(2)this(“hello”);表示先执行本类的有参构造,【进入到C的有参构造器】
(3)super(“hahaa”);代表进入到父类的有参构造,【进入到class B的有参构造】
(4)在B的有参构造中隐藏了一个super,所以要【进入到A的无参构造】
(5)返回第一个信息:我是A类
(6)执行到到B有参,返回第二个信息:hahah我是B类的有参构造
(7)执行到C有参,返回第三个信息:我是C类的有参构造。
(8)执行回C无参,返回第四个信息:我是C类的无参构造。

练习3

1)编写Computer类,包含CPU、内存、硬盘等属性,getDetails方法用于返回Computer的详细信息
2)编写PC子类,继承Computer类,添加特有属性【品牌brand】
3)编写NotePad子类,继承Computer类,添加特有属性【演示color】
4)编写Test类,在main方法中创建PC和NotePad对象,分别给对象中特有的属性赋值,以及从Computer类继承的属性赋值,并使用方法且打印输出信息。

Computer类

public class Computer {
//    1)编写Computer类,包含CPU、内存、硬盘等属性,getDetails方法用于返回Computer的详细信息
    private String CPU;
    private int memory;
    private int disk;

    public Computer(String CPU, int memory, int disk) {
        this.CPU = CPU;
        this.memory = memory;
        this.disk = disk;
    }

    //getDetails方法用于返回Computer的详细信息
    public  String getDetailes(){
        return "cpu =" + CPU + "memory =" + memory + "disk =" + disk;
    }

    public String getCPU() {
        return CPU;
    }

    public void setCPU(String CPU) {
        this.CPU = CPU;
    }

    public int getMemory() {
        return memory;
    }

    public void setMemory(int memory) {
        this.memory = memory;
    }

    public int getDisk() {
        return disk;
    }

    public void setDisk(int disk) {
        this.disk = disk;
    }
}

PC类

public class PC extends  Computer{
//    2)编写PC子类,继承Computer类,添加特有属性【品牌brand】
    private  String brand;

    //这里idea根据调用的规则,自动把调用的构造写好
    //这里也体现出 : 继承设计的基本思想,父类的构造器完成父类属性初始化
    //子类的构造器完成子类属性初始化
    public PC(String CPU, int memory, int disk, String brand) {
        super(CPU, memory, disk);
        this.brand = brand;
    }

    public void printInfo(){
        System.out.println("PC信息 =");
        //调用父类的getDetailes方法,得到相关属性信息。
        System.out.println(getDetailes() + "brand = " + brand);
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }
}

NotePad类

public class NotePad extends  Computer{
//    3)编写NotePad子类,继承Computer类,添加特有属性【演示color】
    private String color;

    public NotePad(String CPU, int memory, int disk, String color) {
        super(CPU, memory, disk);
        this.color = color;
    }

    public void  NoteInfo(){
        System.out.println("NotePad信息 = ");
        System.out.println(getDetailes() + "color = " + color );
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }
}

test类

public class test {
//    4)编写Test类,在main方法中创建PC和NotePad对象,分别给对象中特有的属性赋值,
//    以及从Computer类继承的属性赋值,并使用方法且打印输出信息。
    
    public static void main(String[] args) {
        PC pc = new PC("intel",16,500,"IBM");
        pc.printInfo();

        NotePad note = new NotePad("intel",32,500,"yellow");
        note.NoteInfo();
    }
}

输出

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值