继承、初始化

继承的格式

通过 extends 关键字,可以声明一个子类继承另外一个父类,定义格式如下:

【修饰符】 class 父类 {
    ...
}

【修饰符】 class 子类 extends 父类 {
    ...
}

代码演示

/*
 * 定义动物类Animal,做为父类
 */
class Animal {
    // 定义name属性
    public String name; 
    // 定义age属性
    public int age;
    // 定义动物的吃东西方法
    public void eat() {
        System.out.println(age + "岁的" + name + "在吃东西");
    }
}

/*
 * 定义猫类Cat 继承 动物类Animal
 */
class Cat extends Animal {
    // 定义一个猫抓老鼠的方法catchMouse
    public void catchMouse() {
        System.out.println("抓老鼠");
    }
}

/*
 * 定义测试类
 */
public class ExtendDemo01 {
    public static void main(String[] args) {
        // 创建一个猫类对象
        Cat cat = new Cat();
      
        // 为该猫类对象的name属性进行赋值
        cat.name = "Tom";
      
          // 为该猫类对象的age属性进行赋值
        cat.age = 2;
        
        // 调用该猫的catchMouse()方法
        cat.catchMouse();
        
          // 调用该猫继承来的eat()方法
          cat.eat();
    }
}

演示结果:
抓老鼠
2岁的Tom在吃东西

继承的特点一:成员变量

私有化(private)

  • 父类中的成员,无论是公有(public)还是私有(private),均会被子类继承。
  • 子类虽会继承父类私有(private)的成员,但子类不能对继承的私有成员直接进行访问,可通过继承的公有方法进行访问。

代码如下:

/*
 * 定义动物类Animal,做为父类
 */
class Animal {
    // 定义name属性
    private String name; 
    // 定义age属性
    public int age;
    // 定义动物的吃东西方法
    public void eat() {
        System.out.println(age + "岁的" + name + "在吃东西");
    }
}
/*
 * 定义猫类Cat 继承 动物类Animal
 */
class Cat extends Animal {
    // 定义一个猫抓老鼠的方法catchMouse
    public void catchMouse() {
        System.out.println("抓老鼠");
    }
}

/*
 * 定义测试类
 */
public class ExtendDemo01 {
    public static void main(String[] args) {
        // 创建一个猫类对象
        Cat cat = new Cat();
      
        // 为该猫类对象的name属性进行赋值
        //t.name = "Tom";// 编译报错
      
          // 为该猫类对象的age属性进行赋值
        t.age = 2;
        
        // 调用该猫的catchMouse()方法
        t.catchMouse();
        
          // 调用该猫继承来的eat()方法
          t.eat();
    }
}

成员变量不重名

如果子类父类中出现不重名的成员变量,这时的访问是没有影响的。代码如下:

class Fu {
    // Fu中的成员变量。
    int num01 = 3;
}

class Zi extends Fu {
    // Zi中的成员变量
    int num02 = 4;
    // Zi中的成员方法
    public void show() {
        // 访问父类中的num,
        System.out.println("num1 = " + num1); 
        // 访问子类中的num2
        System.out.println("num2 = " + num2);
    }
}

class ExtendDemo02 {
    public static void main(String[] args) {
        // 创建子类对象
        Zi z = new Zi(); 
          // 调用子类中的show方法
        z.show();  
    }
}

演示结果:
num1 = 3
num2 = 4

成员变量重名

如果子类父类中出现重名的成员变量,这时的访问是有影响的。代码如下:

class Fu {
    // Fu中的成员变量。
    int num = 3;
}

class Zi extends Fu {
    // Zi中的成员变量
    int num = 4;
    public void show() {
        // 访问的num到底是子类还是父类?
        System.out.println("num = " + num);

    }
}
class ExtendsDemo03 {
    public static void main(String[] args) {
          // 创建子类对象
        Zi z = new Zi(); 
          // 调用子类中的show方法
        z.show(); 
    }
}
演示结果:
num = 4

子父类中出现了同名的成员变量时,在子类中需要访问父类中非私有成员变量时,需要使用super 关键字,修饰父类成员变量,类似于之前学过的 this 。

使用格式:

super.父类成员变量名

子类方法需要修改,代码如下:

class Zi extends Fu {
    // Zi中的成员变量
    int num = 6;
    public void show() {
        //访问父类中的num
        System.out.println("Fu num=" + super.num);
        //访问子类中的num
        System.out.println("Zi num=" + this.num);
    }
}
演示结果:
Fu num = 5
Zi num = 6

小贴士:Fu 类中的成员变量是非私有的,子类中可以直接访问。若Fu 类中的成员变量私有了,子类是不能直接访问的。通常编码时,我们遵循封装的原则,使用private修饰成员变量,那么如何访问父类的私有成员变量呢?对!可以在父类中提供公共的getXxx方法和setXxx方法。

练习:代码分析

class Father{
    int a = 10;
    int b = 11;
}
class Son extends Father{
    int a = 20;
    
    public void test(){
        //子类与父类的属性同名,子类对象中就有两个a
        System.out.println("父类的a:" + super.a);//10
        System.out.println("子类的a:" + this.a);//20
        System.out.println("子类的a:" + a);//20
        
        //子类与父类的属性不同名,是同一个b
        System.out.println("b = " + b);//11
        System.out.println("b = " + this.b);//11
        System.out.println("b = " + super.b);//11
    }
    
    public void method(int a){
        //子类与父类的属性同名,子类对象中就有两个成员变量a,此时方法中还有一个局部变量a
        System.out.println("父类的a:" + super.a);//10
        System.out.println("子类的a:" + this.a);//20
        System.out.println("局部变量的a:" + a);//30
    }
}
public class TestInherite2 {
    public static void main(String[] args) {
        Son son = new Son();
        System.out.println(son.a);//20
        
        son.test();
        
        son.method(30);
    }
}

 继承的特点二:成员方法

当类之间产生了关系,其中各类中的成员方法,又产生了哪些影响呢?

成员方法不重名

如果子类父类中出现不重名的成员方法,这时的调用是没有影响的。对象调用方法时,会先在子类中查找有没有对应的方法,若子类中存在就会执行子类中的方法,若子类中不存在就会执行父类中相应的方法。代码如下:

class Fu{
    public void show(){
        System.out.println("Fu类中的show方法执行");
    }
}
class Zi extends Fu{
    public void show2(){
        System.out.println("Zi类中的show2方法执行");
    }
}
public  class ExtendsDemo04{
    public static void main(String[] args) {
        Zi z = new Zi();
         //子类中没有show方法,但是可以找到父类方法去执行
        z.show(); 
        z.show2();
    }
}

成员方法重名——重写(Override)

如果子类父类中出现重名的成员方法,这时的访问是一种特殊情况,叫做方法重写 (Override)。

代码如下:

在父子类的继承关系当中,创建子类对象,访问成员方法的规则:
    创建的对象是谁,就优先用谁,如果没有则向上找。

注意事项:
无论是成员方法还是成员变量,如果没有都是向上找父类,绝对不会向下找子类的。

重写(Override)
概念:在继承关系当中,方法的名称一样,参数列表也一样。

重写(Override):方法的名称一样,参数列表【也一样】。覆盖、覆写。
重载(Overload):方法的名称一样,参数列表【不一样】。

方法的覆盖重写特点:创建的是子类对象,则优先用子类方法。

方法覆盖重写的注意事项:见下面

重写的应用

子类可以根据需要,定义特定于自己的行为。既沿袭了父类的功能名称,又根据子类的需要重新实现父类方法,从而进行扩展增强。比如新的手机增加来电显示头像的功能,代码如下:

class Phone {
    public void sendMessage(){
        System.out.println("发短信");
    }
    public void call(){
        System.out.println("打电话");
    }
    public void showNum(){
        System.out.println("来电显示号码");
    }
}

//智能手机类
class NewPhone extends Phone {
    
    //重写父类的来电显示号码功能,并增加自己的显示姓名和图片功能
    public void showNum(){
        //调用父类已经存在的功能使用super
        super.showNum();
        //增加自己特有显示姓名和图片功能
        System.out.println("显示来电姓名");
        System.out.println("显示头像");
    }
}

public class ExtendsDemo06 {
    public static void main(String[] args) {
          // 创建子类对象
          NewPhone np = new NewPhone();
        
        // 调用父类继承而来的方法
        np.call();
      
          // 调用子类重写的方法
          np.showNum();

    }
}

这里重写时,用到super.父类成员方法,表示调用父类的成员方法。

注意事项
必须保证父子类之间方法的名称相同,参数列表也相同。 @Override:写在方法前面,用来检测是不是有效的正确覆盖重写。 这个注解就算不写,只要满足要求,也是正确的方法覆盖重写。

子类方法的返回值类型必须【小于等于】父类方法的返回值类型(小于其实就是是它的子类)。 小扩展提示:java.lang.Object类是所有类的公共最高父类(祖宗类),java.lang.String就是Object的子类。

注意:如果返回值类型是基本数据类型和void,那么必须是相同

子类方法的权限必须【大于等于】父类方法的权限修饰符。 小扩展提示:public > protected > 缺省 > private 备注:缺省不是汉字缺省,而是什么都不写,留空。

几种特殊的方法不能被重写

静态方法不能被重写
私有等在子类中不可见的方法不能被重写
final方法不能被重写

练习

1、声明父类:Person类 包含属性:姓名,年龄,性别 属性私有化,get/set 包含getInfo()方法:例如:姓名:张三,年龄:23,性别:男

2、声明子类:Student类,继承Person类 新增属性:score成绩 属性私有化,get/set 包含getInfo()方法:例如:姓名:张三,年龄:23,性别:男,成绩:89

3、声明子类:Teacher类,继承Person类 新增属性:salary薪资 属性私有化,get/set 包含getInfo()方法:例如:姓名:张三,年龄:23,性别:男,薪资:10000

public class Person {
    private String name;
    private int age;
    private char gender;
    public Person(String name, int age, char gender) {
        super();
        this.name = name;
        this.age = age;
        this.gender = gender;
    }
    public Person() {
        super();
    }
    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 char getGender() {
        return gender;
    }
    public void setGender(char gender) {
        this.gender = gender;
    }
    
    //包含getInfo()方法:例如:姓名:张三,年龄:23,性别:男
    public String getInfo(){
        return "姓名:" + name + ",年龄:" + age +",性别:" + gender;
    }
}
public class Student extends Person {
    private int score;

    public Student() {
    }

    public Student(String name, int age, char gender, int score) {
        setName(name);
        setAge(age);
        setGender(gender);
        this.score = score;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }
    //包含getInfo()方法:例如:姓名:张三,年龄:23,性别:男,成绩:89
    public String getInfo(){
        //方式一:
//        return "姓名:" + getName() + ",年龄:" + getAge() + ",成绩:" + score;
        
        //方法二:
        return super.getInfo() + ",成绩:" + score;
    }
    
}
public class Teacher extends Person {
    private double salary;

    public Teacher() {
    }

    public Teacher(String name, int age, char gender, double salary) {
        setName(name);
        setAge(age);
        setGender(gender);
        this.salary = salary;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
    
    //包含getInfo()方法:例如:姓名:张三,年龄:23,性别:男,薪资:10000
    public String getInfo(){
        return super.getInfo() + ",薪资:" + salary;
    }
}
public class TestPersonExer2 {
    public static void main(String[] args) {
        Person p = new Person("张三", 23, '男');
        System.out.println(p.getInfo());
        
        Student s = new Student("陈琦", 25, '男', 89);
        System.out.println(s.getInfo());
        
        Teacher t = new Teacher("柴林燕", 18, '女', 11111);
        System.out.println(t.getInfo());
    }
}

继承的特点三:构造方法

原文地址:https://www.cnblogs.com/hbxZJ/p/15483907.html