一、Java面向对象编程

继承

目标

  • 能够理解继承的作用及优点

  • 能够理解this和super的作用

  • 能够理解权限修饰符的作用 public protected 默认 private

  • 能够理解继承下构造方法的执行过程

  • 能够理解子类重写父类的方法

两个类有了父和子的关系,就有了继承,子类会继承父类的成员变量和成员方法

基本语法:

public  class 子类名字 extends 父类名字{
    
}

学生老师类抽取Person练习

老师代码

  • 抽取了共同的属性name和age

  • 共同的方法 show,show里面可以暂时不写内容

public class Person {
    String name;
    int age;

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

    public Person() {
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public void show() {

    }
}

学生类和老师类代码


//extends 继承
public class Student extends Person {
    String id;

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

    public Student() {
    }
}


public class Teacher extends Person {

    double salary;

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

    public Teacher() {
    }
}

测试

public static void main(String[] args) {
    Student stu = new Student();
    Teacher t1 = new Teacher();

    stu.name = "小明";
    System.out.println(stu.getName());
    stu.setAge(10);
    System.out.println(stu.age);
    stu.number = "001";
    System.out.println(stu.number);


    t1.setName("halon");
    t1.setAge(18);
    System.out.println(t1.getName() + "--" + t1.getAge());
    t1.salary = 9999.99;
    System.out.println(t1.salary);
}

继承的好处和坏处

  • 好处:代码的复用性和维护性

  • 坏处:增加了两个类的耦合性(关联性)

super关键字(父类 超类 基类 )

作用:

  • 访问父类构造函数

  • 访问父类成员变量

  • 访问父类成员方法

访问父类构造的学习

构造函数无法继承,子类需要添加自己的空参和有参构造

在子类的有参构造里,使用super调用父类的有参构造,可以更方便的初始化成员变量

public class Sales extends Worker {
    public Sales() {
        System.out.println("执行了空参构造");
    }

    public Sales(String id, String name) {
        //在子类的有参构造里,使用super调用父类的有参构造,可以更方便的初始化成员变量
        super(id, name);
        System.out.println("执行了有参构造");
    }

子类的无参和有参构造都会默认调用父类的无参构造 也就是super()

  • Sales是Worker子类,测试类中空参和有参方式创建了对象

  • 发现Sales里的空参有参构造都默认调用了父类Worker的里无参构造

this可以调用本类的构造

  • 实际工作用,当需要使用空参构造初始化,却希望给成员变量默认值时,可以使用

  • 如下代码,调用空参构造后,用this调用了自己的有参数构造,传入了默认值-1和未知

class Sales extends Worker {
    public Sales(String id, String name) {
        //调用父类的构造
        super(id, name);
        System.out.println("子类 有参");
    }

    public Sales() {
        this("-1", "未知");
        System.out.println("子类 无参");
    }

    public void work() {
        System.out.println("销售产品");
        System.out.println(this);
    }
}

测试代码

Sales s1=new Sales();
Sales s2=new Sales();
Sales s3=new Sales();

System.out.println(s1.name);
System.out.println(s2.name);
System.out.println(s3.name); // 会打印 未知未知未知

如果父类没有空参构造

  • 1 最简单的方法就是补上父类的空参构造

  • 2 子类的有参构造调用父类的有参构造,子类的无参构造调用自己的有参构造

    • 注意传入的值 是每种数据类型的初始化默认值。

public class Student extends Person {
    public Student() {
        this(null,0,null);
    }

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

    String number;
}

构造方法总结

  • 一般我们会在父类 和子类都生成自己需要的空参和有参构造

    • 有参构造里通过super调用父类的有参构造来初始化成员变量,子类特有的成员变量自己调用赋值

    • 如果希望空参构造创建对象有默认值,那么就在空参构造里通过this调用有参构造就可以,传入需要的默认值

    • 父类没有空参构造:补上父类的空参构造或者子类的有参构造调用父类的有参构造,子类的无参构造调用自己的有参构造

  • 注意:super 和this调用构造方法只能2选1,因为语法要求,都要在第一行

访问父类成员变量的学习,super可以调用父类的成员变量

show方法中 分别打印了局部变量age ,当前类的成员变量age,父类的成员变量age

public class Demo01 {
    public static void main(String[] args) {
        Zi zi = new Zi();
        System.out.println(zi.age);//5

        zi.show();
    }
}

//父类
class Fu {
    int age = 100;
}

//子类
class Zi extends Fu {
    int age = 5;

    public void show() {
        int age = 200;
        System.out.println(age); //200 调用局部变量
        System.out.println(this.age); //5  调用本类 成员变量
        System.out.println(super.age);//100 调用父类 成员变量
    }
}

继承关系下代码的执行顺序

  • 父类的成员变量初始化默认值 > 父类构造方法 > 子类成员变量初始化默认值 > 子类构造方法

public class Demo02 {
    public static void main(String[] args) {
        //父类的成员变量初始化默认值 --> 父类构造方法 --> 子类成员变量初始化默认值 --> 子类构造方法
        Zi1 z = new Zi1();
    }
}

//父类
class Fu1 {
    int age = 100;

    public Fu1() {
        System.out.println("Fu");
        System.out.println(this.age);
    }
}

//子类
class Zi1 extends Fu1 {
    double height = 200;

    public Zi1() {
        System.out.println("Zi");
        System.out.println(this.height);
        System.out.println(super.age);//100
    }
}

super和this调用成员方法

  • eat();调用本类成员方法

  • super.eat(); 调用父类 成员方法

public class Demo01 {
    public static void main(String[] args) {
        Zi zi = new Zi();

        zi.show();
    }
}

//父类
class Fu {
    int age = 100;

    public void eat() {
        System.out.println("吃火锅");
    }
}

//子类
class Zi extends Fu {
    int age = 5;

    public void show() {
        eat();
        super.eat();
    }

    public void eat() {
        System.out.println("吃烤鸭");
    }
}

父类中不能被继承的成员:

  • 1、构造方法

  • 2、private私有成员

  • 3、父子类不在同一个包,父类使用默认访问权限的成员不能被继承

权限修饰符 重点掌握private和public就可以

Java中类只支持单继承,不支持多继承,但支持多层继承,类如果没有语法上继承另一个类,那么默认继承Objec

方法重写

子类重写父类的方法

  • 子类出现了和父类中一模一样的方法声明(方法名一样,参数列表也必须一样)

应用场景

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

    父类的功能,又定义了子类特有的内容

代码练习

  • Tudi类继承了Shifu类,重写了skill方法

  • 在子类方法中,可以使用super调用父类的skill

  • ctrl+o 重写的快捷键

  • Override注解 可以检查是不是重写,如果不是,就会报错误

class Shifu {
    public void skill() {
        System.out.println("一阳指");
    }
}

class Tudi extends Shifu {

    //ctrl+o 重写的快捷键
    //注解 Override 检查这个代码是不是重写
    @Override
    public void skill() {
        super.skill();//使用父类的skill
        System.out.println("六脉神剑");
    }
}

方法重写的语法规则:

  • 方法名相同,方法参数列表相同

  • 返回值类型相同(或其子类也可以)

  • 访问修饰符权限不能低于父类

  • 构造方法和私有方法本身就无法继承,也就不存在重写

抽象类

  • 一个有抽象方法的类 必须定义为抽象类 在class 的左侧添加关键字abstract

  • 抽象方法定义时,在返回值类型的左侧 添加关键字abstract

  • 抽象方法主要是为了制定规则,让所有继承的子类都必须实现这个抽象方法

抽象类体验练习

  • 父类Animal 有抽象方法 eat ,注意类也 要写成抽象类

  • 子类Dog,Cat,Tiger继承了Animal ,必须重写父类的抽象方法,否则报错

抽象方法练习

  • 1定义一个抽象类Animal,成员变量name和age

  • 2 里面有2个抽象方法 eat和drink

  • 3 定义类Dog继承Animal 实现方法

  • 4 定义类Cat继承Animal 实现方法

public abstract class Animal{
    String name;
    int age;
    public void eat();
    public void drink();
}
public class Dog extends Animal{
	@Override
    public void eat(){
        System.out.println("狗吃骨头");
    }
    @Override
    public void drink(){
        System.out.println("狗喝可乐");
    }
}
public class Cat extends Animal{
	@Override
    public void eat(){
        System.out.println("猫吃鱼");
    }
    @Override
    public void drink(){
        System.out.println("猫喝雪碧");
    }
}

抽象类 抽象方法特点小结

  • 抽象类中可以有普通方法,可以有抽象方法,也可以没有;

    • 但有抽象方法的类一定是抽象类

  • 抽象类的子类要么重写抽象类中的所有抽象方法,要么子类自己也是抽象类

  • 可以和普通类一样定义成员变量

  • 可以和普通类一样定义构造方法,但是不能实例化

    • 构造方法的作用是用于子类访问父类构造方法时,初始化成员变量

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值