唠唠SE的面向对象-07——继承

论坛 期权论坛 脚本     
匿名技术用户   2020-12-28 14:01   18   0

7. 继承

人属于动物,猪属于动物,等等等……

我们先来模拟几样东西:Student类,Employee类,Person类

//人 类
class Person {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

//学生 类
class Student {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    private int studentID;
    public int getStudentID() {
        return studentID;
    }
    public void setStudentID(int studentID) {
        this.studentID = studentID;
    }
}

//职工 类
class Employee {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    private int id;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
}

我们发现,学生与职工本来就属于人,并且在源代码中存在大量的重复代码。

如果没有继承,类和类的关系将无法描述,就像学生与人的关系一样。。。

继承特点:

1:描述类和类之间的关系

2:降低类和类之间的重复代码

3:降低对象和对象之间的代码重复使用静态变量

4:降低类和类之间的代码重复使用

所以,我们要用一个关键字来描述继承关系:

extends:描述继承关系的关键字

学生继承人,发现学生里的“姓名”属性,在人的class里也都进行了定义。

所以我们可以写成这种形式:

class Person {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

class Student extends Person {
    private int studentID;
    public int getStudentID() {
        return studentID;
    }
    public void setStudentID(int studentID) {
        this.studentID = studentID;
    }
}

Java只支持单继承!!!

1:类名的设定,被继承的类称之为父类(基类),继承的类称之为子类

2:子类并不能继承父类中所有的成员

2.1:父类定义完整的成员(静态成员,非静态,静态变量和静态方法)都可以通过

子类名.父类静态成员 的形式调用成功。

2.2:所有的私有成员不能继承(private修饰的成员)

2.3:构造方法不能被继承

3:不要为了使用继承而继承。职工和学生都有共性的成员,不要为了节省代码,让职工继承学生,那样会显得没有逻辑并且关系也就描述不过去了。。。

super关键字:

子类调用父类的属性/方法

  • super主要存在于子类方法中,用于指向子类对象中父类对象。
  • 访问父类的属性
  • 访问父类的函数
  • 访问父类的构造函数

举个栗子:圆形和矩形都属于图形类

class Graph {
    public double getPerimeter() {
        return 0; // 因为不同的图形,计算方法不一样,所以这里先摆一个空壳
    }
    
    public double getArea() {
        return 0;
    }
}

class Circle extends Graph {
    private double r;

    public double getPerimeter() {
        return Math.PI * 2 * r;
    }

    public double getArea() {
        return Math.PI * r * r;
    }
}

class Rectangle extends Graph {
    private double width, height;

    public double getPerimeter() {
        return 2 * (width + height);
    }

    public double getArea() {
        return width * height;
    }
}

这样可以很明确的看出来这三个类的关系。

Override重写(覆盖、覆写):

在继承中,子类可以定义和父类相同的名称且参数列表一致的方法,将这种方法称之为方法的重写。

1:前提:必须要有继承关系

2:特点

  • 当子类重写了父类的方法,那么子类的对象如果调用该方法,一定调用的是重写过后的方法。可以通过super进行父类的重写方法的调用。
  • 继承可以使得子类可以增强/改写父类的方法

3:细节

3.1: 方法名必须相同

3.2: 参数列表必须相同

3.3: 子类重写父类的方法的时候,方法的访问权限必须大于等于父类的方法的访问权限,否则编译报错

3.4:子类重写父类的方法的时候,返回值类型必须是父类方法的返回值类型或该返回值类型的子类,不能返回比父类更大的数据类型。

4:子类对象查找属性或方法时的顺序:

原则:就近原则。

如果子类的对象调用方法,默认先使用this进行查找。

如果当前对象没有找到属性或方法,找当前对象中维护的super关键字指向的对象。

如果还没有找到,则编译报错,找到则直接调用。

在上面的例子中,圆形和矩形的计算周长和面积的方法都各不相同,所以都需要重写Graph类。

Override与Overload的区别

1:重载(overload):

  • 1:前提:所有的重载方法必须在同一个类中
  • 2:特点:方法名相同,参数列表不同,与其他的无关(访问控制符、返回值类型)
  • 3:三个不同:参数的个数不同、顺序不同、类型不同

2:重写(override):

  • 1:前提:继承
  • 2:特点:方法名必须相同、参数列表必须相同,子类的返回值类型要等于或者小于父类的返回值(继承与多态的思想,多态要到第10节再叨叨)

final关键字放在类上,则不允许被继承。一般两种情况要用final:

1. 为了防止代码功能被重写

2. 该类没有必要进行扩展

说了这么多,最后来一个综合性的例子吧!

  1. 定义动物类,会吃饭、睡觉、叫
  2. 定义猫,继承动物类,重写吃饭、叫
  3. 定义狗,继承动物类,重写睡觉、叫
class Animal {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void eat() {
        System.out.println(name + "米西米西。。。");
    }
    public void sleep() {
        System.out.println(name + "呼呼大睡。。。");
    }
    public void say() {
        System.out.println(name + "发出叫声。。。");
    }
}

class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("阿喵" + super.getName() + "大吃一顿。。。"); // 注意这里不能直接写name,关于该内容放到第12节说明
    }

    @Override
    public void say() {
        System.out.println("阿喵" + this.getName() + "喵喵的叫。。。");
    }
}

class Dog extends Animal {
    @Override
    public void sleep() {
        System.out.println("阿汪" + super.getName() + "睡个跟猪一样。。。");
    }
    
    @Override
    public void say() {
        System.out.println("阿汪" + this.getName() + "汪汪的叫。。。");
    }
}

转载于:https://my.oschina.net/LinkedBear/blog/1615154

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP