编程知识 cdmana.com

Java面向对象 继承、方法的重写、关联和依赖

第1章 继承的概述及特点

1.1 继承的概念

1.1.1 继承的概述 is-a

继承是面向对象的核心特性,是面向对象的学习重点。

继承是代码复用的重要方式,是类与类之间的一种关系。

从类与类之间的设计关系来看,子类必须属于父类的一种时,才会继承。

父类抽取出了共性的内容,子类可以在父类基础上扩展新的属性与行为。

子类拥有父类的所有属性与方法,无需重新定义。并且可以直接使用非私有的父类成员。
关键字 extends

1.1案例

父类

package com.igeek.javase.ch02.extendss;

/** * @version 1.0 * @Description TODO * * 继承: is-a * 1.关键字 extends * 2.继承本质上是设计层面的思想,本意是提高代码的复用性 * 3.子类继承父类后,父类中的成员变量和成员方法子类都具备,并且子类还可以拓展新的属性和新的方法 * 4.创建的父类对象,可以使用父类中的成员属性和成员方法,但是不能使用子类拓展的属性及方法 * 5.Java中类与类之间是单继承 */
public class Animal {
    

    private String name;
    private String color;
    private int age;

    public Animal() {
    
    }

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

    public String getName() {
    
        return name;
    }

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

    public String getColor() {
    
        return color;
    }

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

    public int getAge() {
    
        return age;
    }

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

    //吃
    public Animal eat(/*Animal a*/) /*throws Exception*/{
    
        System.out.println("一只"+color+name+"在吃东西...");
        return null;
    }

}

子类

package com.igeek.javase.ch02.extendss;

/** * @version 1.0 * @Description TODO */
public class Dog extends Animal{
    
    //
    private String player;

    public Dog() {
    
    }

    public Dog(String name, String color, int age, String player) {
    
        super(name, color, age);
        this.player = player;
    }

    public String getPlayer() {
    
        return player;
    }

    public void setPlayer(String player) {
    
        this.player = player;
    }

    //
    public void kanjia(){
    
        System.out.println("一只"+this.getAge()+"的"+this.getName()+"在看家...");
    }

}

1.2 子类通过get&set方法访问父类成员变量

​ 当父类的成员变量用private修饰后,子类无法访问父类的成员变量,但是如果父类提供了public修饰的get/set方法,则子类可以通过get/set方法,正常访问父类的成员变量。

第2章 方法重写及继承内存图解

2.1 方法重写的概念与格式

2.1.1 方法重写的概述

当子类继承父类后,拥有了父类的成员并可以直接调用父类非私有方法。如果子类认为父类提供的方法不够强大,子类可以按照子类自身的逻辑重新定义继承过来的父类方法,这个重新定义父类方法的过程叫做方法重写。

方法重写后,调用该方法时不再调用父类的方法,而调用子类重写后的方法。

package com.igeek.javase.ch02.extendss;

/** * @version 1.0 * @Description TODO * * 方法重载 Overload * 1.发生在一个类中 * 2.方法名相同 * 3.参数列表不同(参数个数、参数顺序、参数数量不同) * 4.与返回值无关 * * 方法重写 Override * 1.发生在继承中,子类继承父类,子类重写父类的方法 * 2.方法名相同 * 3.形参必须一致 * 4.返回值:若是基本数据类型则返回值一致即可; * 若是引用数据类型,则子类的返回值类型不可以放大,只可以是<=父类的返回值类型 Object>Animal>Cat 父类>子类 * 5.访问权限修饰符:子类是不可以缩小范围的 public>protected>(default)>private * 6.抛出异常:子类抛出异常比父类小 Throwable>Exception>NullPointerException * * 注意: * 1.@Override一旦标注在方法上,检测当前方法是否符合重写要求 * 2.子类重写父类的方法后,调用执行时会执行子类重写后的逻辑 */
public class Cat extends Animal{
    

    public Cat() {
    
    }

    public Cat(String name, String color, int age) {
    
        super(name, color, age);
    }

    //捕捉方法
    public void zhua(){
    
        System.out.println("一只"+this.getAge()+"岁的,小"+this.getName()+"在抓鱼...");
    }

    // Alt+Insert -> Override 或者 Ctrl+O
    @Override
    public Cat eat(/*Animal a*/) /*throws NullPointerException*/{
    
        Cat cat = new Cat();
        //默认调用父类的逻辑
        //super.eat();
        System.out.println("一只"+getName()+"在吃鱼...");
        return cat;
    }
}

Test

package com.igeek.javase.ch02.extendss;

/** * @version 1.0 * @Description TODO */
public class Test {
    

    public static void main(String[] args) {
    
        Cat cat = new Cat("小猫咪","花色",2);
        cat.eat();  //Cat中方法重写eat(),执行时会按照子类的逻辑进行执行
        cat.zhua();

        System.out.println("------------------");

        Tiger tiger = new Tiger();
        tiger.setName("东北虎");
        tiger.setColor("白色");
        tiger.setAge(3);
        tiger.eat();
        tiger.hunt();

        System.out.println("------------------");

        Dog dog = new Dog("哈士奇","灰色",5,"彩钢儿");
        dog.eat();
        dog.kanjia();

        System.out.println("------------------");

        Animal animal = new Animal("动物","无色",1);
        animal.eat();
        //animal.hunt();
        //animal.kanjia();
        //animal.zhua();
    }

}

输出

一只小猫咪在吃鱼...
一只2岁的,小小猫咪在抓鱼...
------------------
一只白色东北虎在吃东西...
东北虎在狩猎中...
------------------
一只灰色哈士奇在吃东西...
一只5的哈士奇在看家...
------------------
一只无色动物在吃东西...
  • 是否能被继承?
  •  1.成员变量、成员方法  可以继承
    
  •  2.私有的属性   可以继承
    
  •  3.静态的成员   不可以继承,静态成员是所有实例共享
    
  •  4.构造方法     不可以继承
    
  • 是否能进行方法重写?
  •  1.成员变量不存在重写的问题
    
  •  2.构造方法   不可以重写
    
  •  3.静态方法   不可以重写
    
  •  4.私有方法   不可以重写
    

2.2 继承后子父类构造方法调用先后顺序

2.2.1 继承中子父类构造调用顺序概述

在每次创建子类对象时,我们均会先初始化父类内容,再初始化其子类本身内容。目的在于子类对象中包含了其对应的父类存储空间,便可以包含了其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。

代码体现在子类的构造方法调用时,一定先调用父类的构造方法。

在这里插入图片描述

第3章 this与super

3.1 this与super访问普通成员

3.1.1 this和super访问注意事项

调用普通成员:

this.成员变量 可以访问本类对象的成员变量

super.成员变量 可以访问父类的成员变量

this.成员方法() 可以访问本类对象的成员方法

super.成员方法() 可以访问父类的成员方法

子类方法中

​ 访问子类自身的成员用this.

​ 访问父类的成员super.

就近原则:

​ 局部 > 本类成员 > 父类成员

3.2 super访问父类构造方法

3.2.1 super调用父类构造方法的格式

调用构造方法:

​ this(其他参数) 可以访问本类其他的构造方法

​ super(其他参数) 可以访问父类其他的构造方法

默认子类调用父类构造方法:

​ 子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super();

3.3 this访问子类构造方法

在子类构造中使用this() 或 this(参数类型 参数值…)的方法可以调用本类中的其他构造方法。但是最终都是要调用父类的构造方法,完成父类成员的初始化。

第4章 关联关系及依赖关系

4.1 关联关系

​ 对象和对象之间的连接。在Java中,关联关系的代码表现形式为一个类做为另一个类的属性类型存在。即“有”的关系:”has-a”

  • 关联关系 为了提高代码的复用率
  • 1.代码层面:一个类作为另外一个类的属性类型存在
    
  •  2.has-a   有
    
  •  3.一对一  、 一对多Phone[] phones、List<Phone> list
    
  •  4.强关联(组合关系)、弱关联(聚合关系)
    
  •  5.单向关联、双向关联
    
package com.igeek.javase.ch02.has;

import java.util.Arrays;

/** * @version 1.0 * @Description 关联关系 */
public class ClassTest {
    

    public static void main(String[] args) {
    
        Student stu1 = new Student("小红",100);
        Student stu2 = new Student("小黑",101);
        Student stu3 = new Student("小白",102);
        Student[] stus = {
    stu1,stu2,stu3};

        Classes classes = new Classes("Java","班级1",stus);
// classes.setStudents(stus);

        stu1.setClasses(classes);
        stu2.setClasses(classes);
        stu3.setClasses(classes);

        //双向关联中 , toString()会互相调用的问题,造成堆栈溢出错误 , 一定要注意
        System.out.println(classes);
        System.out.println("-----------"+classes.getName()+"的学生信息如下------------");
        for (Student student : classes.getStudents()) {
    
            System.out.println(student);
        }
    }

}
class Classes{
    
    private String label;
    private String name;

    //一对多 强关联 双向关联
    private Student[] students = new Student[3];

    public Classes() {
    
    }

    public Classes(String label, String name) {
    
        this.label = label;
        this.name = name;
    }

    public Classes(String label, String name, Student[] students) {
    
        this.label = label;
        this.name = name;
        this.students = students;
    }

    /** * 获取 * @return label */
    public String getLabel() {
    
        return label;
    }

    /** * 设置 * @param label */
    public void setLabel(String label) {
    
        this.label = label;
    }

    /** * 获取 * @return name */
    public String getName() {
    
        return name;
    }

    /** * 设置 * @param name */
    public void setName(String name) {
    
        this.name = name;
    }

    /** * 获取 * @return students */
    public Student[] getStudents() {
    
        return students;
    }

    /** * 设置 * @param students */
    public void setStudents(Student[] students) {
    
        this.students = students;
    }

    /*public String toString() { return "Classes{label = " + label + ", name = " + name + ", students = " + Arrays.toString(students) + "}"; //StackOverflowError 堆栈溢出 }*/
    public String toString() {
    
        return "Classes{label = " + label + ", name = " + name + "}";
    }
}
class Student{
    
    private String name;
    private int num;

    //一对一 弱关联 双向关联
    private Classes classes;

    public Student() {
    
    }

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

    public Student(String name, int num, Classes classes) {
    
        this.name = name;
        this.num = num;
        this.classes = classes;
    }

    /** * 获取 * @return name */
    public String getName() {
    
        return name;
    }

    /** * 设置 * @param name */
    public void setName(String name) {
    
        this.name = name;
    }

    /** * 获取 * @return num */
    public int getNum() {
    
        return num;
    }

    /** * 设置 * @param num */
    public void setNum(int num) {
    
        this.num = num;
    }

    /** * 获取 * @return classes */
    public Classes getClasses() {
    
        return classes;
    }

    /** * 设置 * @param classes */
    public void setClasses(Classes classes) {
    
        this.classes = classes;
    }

    public String toString() {
    
        return "Student{name = " + name + ", num = " + num + ", classes = " + classes + "}";
    }
}

4.2 依赖关系

依赖关系(use-a):指一个类A使用到了另一个类B。依赖关系的特性:这种关系是具有偶然性的、临时性的、非常弱的,但是类B的变化会影响到类A。

  • 依赖关系 为了代码复用性
  •   1.代码层面  一个类作为另外一个类的方法形参类型存在
    
  •   2.use-a  用
    
  •   3.具备临时性,偶然性
    
public class Person {
    

    private String name;

    //上班的方法 类A使用到了另一个类B
    public void work(Bus bus){
    
        System.out.println(this.name+"乘坐"+bus.getName()+"去上班");
    }

    public Person() {
    
    }

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

    /** * 获取 * @return name */
    public String getName() {
    
        return name;
    }

    /** * 设置 * @param name */
    public void setName(String name) {
    
        this.name = name;
    }

    public String toString() {
    
        return "Person{name = " + name + "}";
    }
}

版权声明
本文为[朝上]所创,转载请带上原文链接,感谢
https://blog.csdn.net/m0_51051154/article/details/120096186

Scroll to Top