• 继承、初始化


    继承的格式

    通过 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());
        }
    }

    继承的特点三:构造方法

  • 相关阅读:
    bzoj 2599
    bzoj 3697
    poj 1741
    bzoj 2741
    bzoj 5495
    bzoj 3261
    网络流24题——骑士共存问题 luogu 3355
    网络流24题——数字梯形问题 luogu 4013
    bzoj 3998
    网络流24题——魔术球问题 luogu 2765
  • 原文地址:https://www.cnblogs.com/hbxZJ/p/15483907.html
Copyright © 2020-2023  润新知