Java学习day12-面向对象特征之二:继承

一、继承

  继承的概念:

    继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。

  为什么要有继承?

    多个类中存在相同的属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。

    把共性的东西抽取出来形成父类(基类或超类),实际需求的子类在继承父类的基础上写自己特有代码即可。

  类继承的语法规则:

    在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的,一般形式如下:

class 父类 {
}
 
class 子类 extends 父类 {
}

  例如:创建一个子类Student并继承父类Person的某些属性和方法

//创建一个父类Person
package day12;

public class Person {
    int age;
    String name;
    int sex;
    
    public void showInfo(){
        System.out.println(this.age);
        System.out.println(this.name);
        System.out.println(this.sex);
    }
}



//创建一个子类Student
package day12;

public class Student extends Person{
    String school;
    
    public void showInfo(){
        System.out.println(this.age);
        System.out.println(this.name);
        System.out.println(this.sex);
        System.out.println(this.school);
    }
}
//Student类继承了父类Person的所有属性和方法,
//并增加了一个属性school.Person中的属性和方法,student都可以利用。

  继承的作用:

    1.继承的出现提高了代码的复用性。

    2.继承的出现让类与类之间产生了关系,提供了多态的前提。

    3.继承是有逻辑关系在里面的,不要仅为了获取其他类中的某个功能而去继承。

    4.子类继承了父类,就继承了父类的方法和属性。

    5.在子类中,可以使用父类中定义的方法和属性,也可以创建新的数据和方法。

    6.在Java中,继承的关键字用的是“extends”,即子类不是父类的子集,而是对父类的“扩展”。

  注意:关于继承的规则

    子类不能直接访问父类中私有的(private)的成员变量和方法。

    (但是可以通过其他操作访问父类的私有操作:比如通过setter或getter方法)

二、单继承和多层继承

  类的继承:

    Java只支持单继承,不允许多重继承,但允许多层继承。

      1.一个子类只能有一个父类

      2.一个父类可以派生出多个子类

  实例1:(1)定义一个ManKind类,包括:

        1.成员变量int sex和int salary;

        2.方法void manOrWoman():根据sex的值显示“man”(sex==1)或者“woman”(sex==0);

        3.方法void employeed():根据salary的值显示“no job”(salary==0)或者“job”(salary!=0)。

      (2)定义类Kids继承ManKind,并包括:

        1.成员变量int yearsOld;

        2.方法printAge()打印yearOld的值。

     (3)在Kids类的main方法中实例化Kids的对象someKid,用该对象访问其父类的成员变量及方法。

package day12;

public class ManKind {//定义一个ManKind类
    int sex;
    int salary;
            
    public int getSex() {
        return sex;
    }


    public void setSex(int sex) {
        this.sex = sex;
    }


    public int getSalary() {
        return salary;
    }


    public void setSalary(int salary) {
        this.salary = salary;
    }


    public void manOrWoman(){
        if (this.sex == 1){
            System.out.println("man");
        }else if(this.sex == 0){
            System.out.println("woman");
        }
    }
    
    
    public void  employeed(){
        if(this.salary == 0){
            System.out.println("no job");
        }else{
            System.out.println("job");
        }
    }
}



package day12;

public class Kids extends ManKind{//定义类Kids继承ManKind类
    int yearsOld;

    public int getYearsOld() {
        return yearsOld;
    }

    public void setYearsOld(int yearsOld) {
        this.yearsOld = yearsOld;
    }

    public void printAge(){
        System.out.println(this.yearsOld);
    }
    
    public static void main(String[] args){
        Kids someKid = new Kids();
        someKid.setSex(0);
        someKid.setSalary(100);
        
        someKid.manOrWoman();
        someKid.employeed();
    }
}

打印结果为:

三、方法的重写(override)

  定义:

    在子类中可以根据需要对从父类中继承来的方法进性改造,也称方法的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法。

  要求:

    1.重写方法必须和被重写方法具有相同的方法名称、参数列表和返回值类型。(子类重写父类的方法,只是重写编写方法体的代码)

    2.重写方法不能使用比被重写方法更为严格的访问权限。

    3.重写的方法和被重写的方法必须同时为static的,或者同时为非static的。

    4.子类方法抛出的异常不能大于父类被重写方法抛出的异常。

实例(2)在实例1中用子类Student对Person类的showInfo方法进行重写

 1 package day12;
 2 
 3 public class Person {
 4     int age;
 5     String name;
 6     int sex;
 7     
 8     public void showInfo(){
 9         System.out.println(this.age);
10         System.out.println(this.name);
11         System.out.println(this.sex);
12     }
13     
14     public void setInfo(int age, String name, int sex){
15         this.age = age;
16         this.name = name;
17         this.sex = sex;
18     }
19 }
20 
21 
22 
23 package day12;
24 
25 public class Student extends Person{
26     String school;
27     
28 //    public void showInfo(){
29 //        System.out.println(this.age);
30 //        System.out.println(this.name);
31 //        System.out.println(this.sex);
32 //        System.out.println(this.school);
33 //    }
34     
35     public void showInfo() {//@Override,用快捷键Alt+/
36         // TODO Auto-generated method stub
37         System.out.println("以下是Student类对Person类的showInfo方法的重写");
38         System.out.println(this.age);
39         System.out.println(this.name);
40         System.out.println(this.sex);
41     }
42     
43 //    public void setInfo(int age, String name, int sex) {
44 //        // TODO Auto-generated method stub
45 //        System.out.println(age);
46 //        System.out.println(name);
47 //        System.out.println(sex);
48 //    }
49 
50     public static void main(String[] args){
51         Student stu = new Student();
52         stu.showInfo();
53     }
54 }

打印结果为:

 注意:正确区分方法的重载和方法的重写

    重载:一个类可以有多个同名方法

    重写:子类可以重新写父类的方法,覆盖父类的方法

实例(3)修改实例(1)中定义的类Kids,在Kids中重新定义employed()方法,覆盖父类ManKind中定义的employed()方法,输出“Kids should study and no job.”

 1 package day12;
 2 
 3 public class Kids extends ManKind{
 4     int yearsOld;
 5 
 6     public int getYearsOld() {
 7         return yearsOld;
 8     }
 9 
10     public void setYearsOld(int yearsOld) {
11         this.yearsOld = yearsOld;
12     }
13 
14     public void printAge(){
15         System.out.println(this.yearsOld);
16     }
17     
18     /**
19      * 重写了父类的employed方法
20      * */
21     public void employeed() {
22         // TODO Auto-generated method stub
23         System.out.println("Kids should study and no job");
24     }
25     
26     public static void main(String[] args){
27         Kids someKid = new Kids();
28         someKid.setSex(0);
29         someKid.setSalary(100);
30         
31         someKid.manOrWoman();
32         someKid.employeed();
33     }
34 }

打印结果为:

  四种访问权限修饰符补充

    1.如果子类和父类在同一个包下,那么对于父类的成员修饰符只要不是私有的private,那么子类就都可以使用。

    2.如果子类和父类不再同一个包下,那么子类只能使用父类中protected和public修饰的成员变量。

四、关键字super

  在Java中使用super来调用父类中的指定操作:

    1.super可用于访问父类中定义的属性。

    2.super可用于调用父类中定义的成员方法。

    3.super可用于在子类中构造方法中调用父类的构造器。

  注意;

    1.尤其是当子父类出现同名成员时,可以用super进行区分。

    2.super的追溯不仅限于直接父类,可以调用子类之上的所有父类层级。

    3.super和this的用法相像,this代表本类对象的引用,super代表父类的内存空间的标识。

实例(4)修改实例1中定义的类Kids的employed()方法,在该方法中调用父类ManKind的employed方法,然后再输出"but Kids should study and no job"。

 1 package day12;
 2 
 3 public class Kids extends ManKind{
 4     int yearsOld;
 5 
 6     public int getYearsOld() {
 7         return yearsOld;
 8     }
 9 
10     public void setYearsOld(int yearsOld) {
11         this.yearsOld = yearsOld;
12     }
13 
14     public void printAge(){
15         System.out.println(this.yearsOld);
16     }
17     
18     /**
19      * 重写了父类的employed方法
20      * */
21     public void employeed() {
22         // TODO Auto-generated method stub
23     //    System.out.println("Kids should study and no job");
24         
25         super.employeed();//调用父类ManKind的employed()方法
26         System.out.println("but Kids should study and no job");//输出“but Kids should study and no job”
27     }
28     
29     public static void main(String[] args){
30         Kids someKid = new Kids();
31         someKid.setSex(0);
32         someKid.setSalary(100);
33         
34         someKid.manOrWoman();
35         someKid.employeed();
36     }
37 }

打印结果为:

 

  关键字super调用父类的构造器

.      1.子类中所有的构造器默认都会访问父类中空参数的构造器。

    2.当父类中没有空参数的构造器时,子类的构造器必须通过this(参数列表)或者super(参数列表)语句指定调用本类或者父类中相应的构造器,且必须放在构造器的第一行。

    3.如果子类构造器中既未显示调用父类或本类的构造器,且父类中又没有无参的构造器,则编译会出错。

 实例(5)在父类ManKind中构造一个空参数的构造器,子类Kids的构造器会默认访问

 1 package day12;
 2 
 3 public class ManKind {
 4     public ManKind(){//显示构造一个无参的构造器
 5         System.out.println("ManKind的无参构造器");
 6     }
 7     int sex;
 8     int salary;
 9             
10     public int getSex() {
11         return sex;
12     }
13 
14 
15     public void setSex(int sex) {
16         this.sex = sex;
17     }
18 
19 
20     public int getSalary() {
21         return salary;
22     }
23 
24 
25     public void setSalary(int salary) {
26         this.salary = salary;
27     }
28 
29 
30     public void manOrWoman(){
31         if (this.sex == 1){
32             System.out.println("man");
33         }else if(this.sex == 0){
34             System.out.println("woman");
35         }
36     }
37     
38     
39     public void  employeed(){
40         if(this.salary == 0){
41             System.out.println("no job");
42         }else{
43             System.out.println("job");
44         }
45     }
46 }
47 
48 
49 package day12;
50 
51 public class Kids extends ManKind{
52     int yearsOld;
53 
54     public int getYearsOld() {
55         return yearsOld;
56     }
57 
58     public void setYearsOld(int yearsOld) {
59         this.yearsOld = yearsOld;
60     }
61 
62     public void printAge(){
63         System.out.println(this.yearsOld);
64     }
65     
66     /**
67      * 重写了父类的employed方法
68      * */
69     public void employeed() {
70         // TODO Auto-generated method stub
71     //    System.out.println("Kids should study and no job");
72         
73         super.employeed();//调用父类ManKind的employed()方法
74         System.out.println("but Kids should study and no job");//输出“but Kids should study and no job”
75     }
76     
77     public static void main(String[] args){
78         Kids someKid = new Kids();//new Kids()是在调用Kids类的默认的无参构造方法,在这个过程中就会使用父类的无参构造,打印出“ManKind的无参构造器”这句话
79 //        someKid.setSex(0);
80 //        someKid.setSalary(100);
81 //        
82 //        someKid.manOrWoman();
83 //        someKid.employeed();
84     }
85 }

打印结果:

实例(6)在父类ManKind中构造一个有参数的构造器,子类Kids的构造器必须通过super(参数列表)语句指定调用本类或者父类中相应的构造器,且必须放在构造器的第一行。

 1 package day12;
 2 
 3 public class ManKind {
 4 //    public ManKind(){//显示构造一个无参的构造器
 5 //        System.out.println("ManKind的无参构造器");
 6 //    }
 7     
 8     //当存在显示的构造方法时,类就没有默认的无参构造了,而是要使用显示的构造
 9     public ManKind(int sex, int salary){//显示构造一个有参的构造器
10         this.sex = sex;
11         this.salary = salary;
12     }
13     
14     int sex;
15     int salary;
16             
17     public int getSex() {
18         return sex;
19     }
20 
21 
22     public void setSex(int sex) {
23         this.sex = sex;
24     }
25 
26 
27     public int getSalary() {
28         return salary;
29     }
30 
31 
32     public void setSalary(int salary) {
33         this.salary = salary;
34     }
35 
36 
37     public void manOrWoman(){
38         if (this.sex == 1){
39             System.out.println("man");
40         }else if(this.sex == 0){
41             System.out.println("woman");
42         }
43     }
44     
45     
46     public void  employeed(){
47         if(this.salary == 0){
48             System.out.println("no job");
49         }else{
50             System.out.println("job");
51         }
52     }
53 }
54 
55 
56 
57 package day12;
58 
59 public class Kids extends ManKind{
60     public Kids(int sex, int salary) {
61         //在父类只有有参构造可以使用的时候,子类必须显示的构建一个构造来调用父类的有参构造,并且调用父类的构造方法要写在第一行。
62         super(sex, salary);// super调用父类的构造方法要写在第一行
63     }
64 
65     int yearsOld;
66 
67     public int getYearsOld() {
68         return yearsOld;
69     }
70 
71     public void setYearsOld(int yearsOld) {
72         this.yearsOld = yearsOld;
73     }
74 
75     public void printAge(){
76         System.out.println(this.yearsOld);
77     }
78     
79     /**
80      * 重写了父类的employed方法
81      * */
82     public void employeed() {
83         // TODO Auto-generated method stub
84     //    System.out.println("Kids should study and no job");
85         
86         super.employeed();//调用父类ManKind的employed()方法
87         System.out.println("but Kids should study and no job");//输出“but Kids should study and no job”
88     }
89     
90     public static void main(String[] args){
91 //        Kids someKid = new Kids();//new Kids()是在调用Kids类的默认的无参构造方法,在这个过程中就会使用父类的无参构造
92 //        someKid.setSex(0);
93 //        someKid.setSalary(100);
94 //        
95 //        someKid.manOrWoman();
96 //        someKid.employeed();
97     }
98 }

  关键字this和super的区别

    

    注意:在子类中,通过this或者是super调用构造器,只能使用其中一个,因为都要占据第一行。(NO.3)

五、简单类对象的实例化过程

 

posted @ 2019-12-30 19:59  苏胖胖  阅读(393)  评论(0)    收藏  举报