11_Java中的继承

Java中的继承

一、继承概述

1、继承概述:

在类中:有一些类具有一些相同的属性和方法,即相同的一些特征。

继承是面向对象的三大特性之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义、追加属性和方法

2、继承格式:

格式:

public class 子类名 extends 父类名{}	//extends 继承、扩展
//示例:
public class Son extends Base{}
//Son:	是子类,也称为派生类
//Base:	是父类,也称为基类,超类
3、继承中子类的特点:

子类可以有父类的内容

子类还可以有自己特有的内容

思考?当子类与父类中有同名属性和方法时,调用时如何区分?

二、继承的好处和弊端

1、继承的好处:

提高了代码的复用性(多个类相同的成员可以放到同一个类中)

提高了代码的维护性(如果方法需要修改,只用将父类修改既可)

2、继承的弊端:

继承让类之间产生了关系,类的耦合性增强了,当父类发生变化时子类实现也不得不跟着变化,削弱了子类的独立性

3、什么时候使用继承:

继承体现的关系:is a

假设法:我有两个类A和B,如果他们满足A是B的一种,或者B是A的一种,就说明他们之间存在继承关系,这个时候就可以考虑使用继承来实现,否则就不能滥用继承。

举例:苹果 和 水果,猫 和 动物

三、继承中变量访问的特点:

在子类的方法中访问一个变量时访问优先顺序是

1、子类局部范围(方法中)找

2、子类成员范围(本类中)找

3、父类成员范围(父类中)找

如果都没有就报错:注意这里只考虑到父亲,父亲以上不考虑

package com.itheima_02;
/*
父类
 */
public class Base {
    //成员变量
    public int age = 40;    //此处为了测试使用public权限
}
package com.itheima_02;
/*
子类
 */
public class Son extends Base{
    //成员属性
    public int height = 175;    //身高

    public int age = 20;        //年龄 当子类中存在这个成员属性时会优先调用自己的

    //show方法
    public void show(){
        int age = 30;           //没有用this指针来指明是 又优先使用的方法里面的age变量
        System.out.println(age);
        System.out.println(height);
        //报错 方法中找不到->本类中找不到->父类中也找不到
//        System.out.println(weight);
    }
}
package com.itheima_02;
/*
测试类
 */
public class Demo {
    public static void main(String[] args){
        //创建对象,调用方法
        Son s = new Son();
        s.show();
    }
}

四、super关键字

1、super与this:

用于访问父类成员变量

在Java中貌似没有作用域的方法:

super关键字的用法和this关键字的用法相似

this:代表本类对象的引用

super:代表父类存储空间的标识(可以理解为父类对象引用)

2、两个关键字的使用:

关键字 访问成员变量 访问构造方法 (...表示参数) 访问成员方法
this this.成员变量 访问本类成员变量 this(...) 访问本类构造方法 this.成员方法名(...) 访问成员方法
super super.成员变量 访问父类成员变量 super(...) 访问父类构造方法 super.成员方法(...) 访问父类成员方法

3、参考代码:

package com.itheima_03;
/*
父类
 */
public class Base {
    public int age = 40;
}
package com.itheima_03;
/*
子类
 */
public class Son extends Base{
    public int age = 20;

    public void show(){
        int age = 30;
        System.out.println(age);

        //需求,访问本类中的成员变量? this指针
        System.out.println(this.age);

        //我要访问父类的成员变量?  super
        System.out.println(super.age);
    }
}
package com.itheima_03;
/*
测试类
 */
public class Demo {
    public static void main(String[] args){
        //创建对象,调用方法
        Son s = new Son();
        s.show();

    }
}

4、参考(看着玩就行):

//C++中可以通过作用域 来区分调用 子类、父类、方法中 同名变量 的位置
#include <iostream>
using namespace std;
class Base 
{
public:
	int age = 40;
};

class Son :public Base 
{
public:
	int age = 20;

public:
	void show() 
	{
		int age = 10;
		//调用父类
		cout << Base::age << endl;
		//调用子类
		cout << Son::age << endl;	//或者cout<<this->age<<endl;
		//调用方法中的变量
		cout << age << endl;
	}
};

int main()
{
	Son s;
	s.show();

	system("pause");
	return 0;
}

五、继承中构造方法的访问特点:

理解提示:先有父亲 才能 有你,所以父类先要初始化

1、子类中的所有的构造方法默认都会访问父类中无参构造方法

为什么?

1、因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化

2、每一个子类构造方法的第一条语句默认都是:super() -> 表示调用父类构造函数 括号中无参数所以都是访问的父类无参构造

2、父类中没有无参构造方法,只有带参构造方法 或者说 我们想要先调用的是父类中的有参构造方法

1、通过修改默认语句:super(); 为 super(参数列表); 来解决这两个问题

2、如果只是前者,我们推荐补全父类无参构造

3、参考代码:
package com.itheima_04;
/*
父类
 */
public class Base {
    public Base(){
        System.out.println("父类无参构造方法被调用");
    }

    public Base(int age){
        System.out.println("父类有参构造方法被调用");
    }
}

package com.itheima_04;
/*
子类
 */
public class Son extends Base{
    public Son(){
//        super();  默认存在可以不写
// 如果 需要调用父类中的带参构造方法(或者父类无无参构造:写了有参没写无参)就 使用带参语句super(参数列表);
        super(10);
        System.out.println("子类无参构造方法被调用");
    }

    public Son(int age){
//        super();  默认存在可以不写
        super(10);    //如果 需要调用父类中的带参构造方法就 使用带参语句super(参数列表);
        System.out.println("子类有参构造方法被调用");
    }
}
package com.itheima_04;
/*
测试类
 */
public class Demo {
    public static void main(String[] args) {
        //创建对象
        Son s = new Son();  //可以发现先调用了父类的无参构造

        Son s2 = new Son(10);

    }
}

六、继承中成员方法的访问特点

通过子类对象访问一个方法

1、子类范围找

2、父类范围找

如果还没找到就报错(同变量,不考虑父亲的父...)

package com.itheima_05;
/*
父类
 */
public class Base {
    public Base(){};


    public void show(){
        System.out.println("父类中show方法的调用");
    }
}
package com.itheima_05;
/*
子类
 */
public class Son extends Base{
    public Son(){};

    public void method(){
        System.out.println("子类中method方法的调用");
    }

    public void show(){
        super.show();
        System.out.println("子类中show方法被调用");
    }
}
package com.itheima_05;
/*
测试类
 */
public class Demo {
    public static void main(String[] args){
        //创建对象调用方法
        Son s = new Son();
        s.method();

        s.show();
    }
}

总结:继承中的成员(包括方法和属性)由子类创建对象进行(同名成员)调用时是由近到远来寻找,也可以通过this与super关键字来直接限定调用和使用;而对于构造方法会通过默认语句调用父类无参,也可以通过修改默认语句调用有参构造方法

七、super内存图:

略...

八、方法重写

一、方法重写的概述:

1、方法重写概述:

子类中出现了和父类中一摸一样的方法声明

2、方法重写的应用:

当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容

3、练习手机类和新手机类:

@Override

是一个注释(注解后面会学习到)

可以帮助我们检查重写方法的方法声明的正确性

二、方法重写注意事项:

1、私有方法不能被重写(父类私有成员子类是不能继承的)

2、子类方法的访问权限不能更低(public > 默认 > private)

3、参考代码:

package com.itheima_07;
/*
父类
 */
public class Base {
    private void show(){
        System.out.println("父类中show()方法被调用");
    }

    void method(){
        System.out.println("父类中method()方法被调用");
    }

}
package com.itheima_07;
/*
子类
 */
public class Son extends Base{
    //子类不能继承父类中的 私有内容
    /* @Override
    private void show(){
        System.out.println("子类中show()方法被调用");
    }*/

   /* @Override
    public void method(){
        System.out.println("父类中method()方法被调用");
    }*/

    @Override
    public void method(){  //当不提供访问权限修饰符时 默认提供一个
        System.out.println("父类中method()方法被调用");
    }
}

九、Java中继承的注意事项

1、Java中类只支持单继承,不支持多继承

2、Java中类支持多层继承

3、参考代码:

package com.itheima_08;

public class Granddad {
    public void drink(){
        System.out.println("爷爷爱喝酒");
    }
}
package com.itheima_08;

public class Father extends Granddad{
    public void NoSmoke(){
        System.out.println("爸爸不爱抽烟");
    }
}
package com.itheima_08;

public class Mother {
    public void dance(){
        System.out.println("妈妈爱跳舞");
    }
}
package com.itheima_08;

/*  在Java中不支持多继承
public class Son extends Father, Mother{

}*/

public class Son extends Father{

}

十、继承案例

1、老师学生:

需求:先定义一个老师类和一个学生类,再抽取这两个类中的共性内容创建一个父类

package com.itheima_10;
/*
人类
 */
public class Person {
    private String name;
    private int age;

    public Person(){};

    public Person(String name, int age){
        this.name = name;
        this.age = age;
    }

    public void setName(String name){
        this.name = name;
    }

    public String getName(){
        return this.name;
    }

    public void setAge(int age){
        this.age = age;
    }

    public int getAge(){
        return age;
    }
}
package com.itheima_10;
/*
学生类
 */
public class Student extends Person{
    //添加构造方法
    public Student(){};

    public Student(String name, int age){
//        this.name = name;	
//        this.age = age;
        super(name, age);
    }

    public void study(){
        System.out.println("好好学习,天天向上");
    }
}
package com.itheima_10;
/*
老师类
 */
public class Teacher extends Person{
    public Teacher(){}  //手动提供了无参构造,因为下面有有参构造

    public Teacher(String name, int age){
        //此处无法访问父类的私有权限
//        this.name = name;
//        this.age = age;
        super(name, age);
    }

    public void teach(){
        System.out.println("用爱成就每一位学生");
    }
}
package com.itheima_10;
/*
测试类
 */
public class PersonDemo {
    public static void main(String[] args){
        //1、创建一个老师类对象
        //无参构造
        Teacher t1 = new Teacher();
        t1.setName("张三");
        t1.setAge(30);
        System.out.println(t1.getName() + "," + t1.getAge());
        t1.teach();
        //有参构造
        Teacher t2 = new Teacher("李四", 33);
        System.out.println(t2.getName() + "," + t2.getAge());
        t2.teach();

        //2、创建一个学生类对象
        //无参构造
        Student s1 = new Student();
        s1.setName("小明");
        s1.setAge(18);
        System.out.println(s1.getName() + "," + s1.getAge());
        s1.study();

        //有参构造
        Student s2 = new Student("小红", 19);
        System.out.println(s2.getName() + "," + s2.getAge());
        s1.study();
    }
}

2、猫和狗:

package com.itheima_11;
/*
动物类
 */
public class Animal {
    //成员变量
    private String name;
    private int age;
    //构造方法
    public Animal(){};

    public Animal(String name, int age){
        this.name = name;
        this.age = age;
    }

    //set/get/show方法
    public void setName(String name){
        this.name = name;
    }

    public String getName(){
        return this.name;
    }

    public void setAge(int age){
        this.age = age;
    }

    public int getAge(){
        return this.age;
    }

    public void show(){
        System.out.println(getName() + "," + getAge());
    }
}
package com.itheima_11;
/*
猫类
 */
public class Cat extends Animal{
    //构造函数
    public Cat() {
    }

    public Cat(String name, int age) {
        //这里不能使用 this
        // 应为本类中没有提供这两个属性 而且父类中这两个属性是private没有继承过来
        super(name, age);
    }

    public void catchMouse(){
        System.out.println("猫抓老鼠");
    }
}
package com.itheima_11;
/*
狗类
 */
public class Dog extends Animal{
    //构造方法
    public Dog() {
    }

    public Dog(String name, int age) {
        //这里不能使用 this
        // 应为本类中没有提供这两个属性 而且父类中这两个属性是private没有继承过来
        super(name, age);
    }

    public void lookDoor(){
        System.out.println("狗看门");
    }
}
package com.itheima_11;
/*
测试类
 */
public class AnimalDemo {
    public static void main(String[] args){
        //创建猫类对象并进行测试
        Cat c1 = new Cat();
        c1.setName("加菲猫");
        c1.setAge(5);
        System.out.println(c1.getName() + "," + c1.getAge());
        c1.catchMouse();

        Cat c2 = new Cat("汤姆猫", 7);
        System.out.println(c2.getName() + "," + c2.getAge());
        c2.catchMouse();

        //创建狗类对象并进行测试
        Dog d1 = new Dog();
        d1.setName("旺财");
        d1.setAge(5);
        System.out.println(d1.getName() + "," + d1.getAge());
        d1.lookDoor();

        Dog d2 = new Dog("来福", 8);
        System.out.println(d2.getName() + "," + d2.getAge());
        d2.lookDoor();
    }
}
posted @ 2022-10-02 20:45  如此而已~~~  阅读(33)  评论(0编辑  收藏  举报