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)
五、简单类对象的实例化过程



浙公网安备 33010602011771号