Java从零开始学十五(继承)
一、继承作用
继承使用复用以前的代码非常容易,能够大大的缩短开发周期,降低开发成本,同时增加程序的易维护性
继承使重一个类A能够直接使用另外一个类B的属性和方法的一种途径
类A可以有自己的属性和方法
二、继承实现
package com.pb.person; /* * 父类 */ public class Person { private String name; //姓名 private String sex; //性别 private int age;//年龄 //设置getter和setter方法 public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { if(sex.equals("男") || sex.equals("女")){ //设置性别限制,不合法的值将提示错误 this.sex = sex; }else{ System.out.println("性别不合法,性别只能是:男或者女"); } } public int getAge() { return age; } public void setAge(int age) { if(age>0 && age<=150){ //设置年龄限制 this.age = age; }else{ System.out.println("年龄只能在1-150岁之间"); } } public Person() { this.name = "无名氏"; this.sex = "男"; this.age = 22; } public Person(String name, String sex, int age) { this.name = name; this.sex = sex; this.age = age; } public void say(){ System.out.println("自我介绍:"); System.out.println("姓名:"+this.name); System.out.println("性别:"+this.sex); System.out.println("年龄:"+this.age); } }
子类:
package com.pb.person; /* * 子类 */ public class Student extends Person { private int stuNo ; //学号 private String specialty; //专业 public Student() { } public Student(String name, String sex, int age,int stuNo,String specialty) { super(name, sex, age); this.stuNo=stuNo; this.specialty=specialty; } //getter/setter方法 public int getStuNo() { return stuNo; } public void setStuNo(int stuNo) { this.stuNo = stuNo; } public String getSpecialty() { return specialty; } public void setSpecialty(String specialty) { this.specialty = specialty; } }
测试类
package com.pb.persontest; import com.pb.person.Student; public class Test { public static void main(String[] args) { Student stu=new Student("张三", "男", 22, 121, "计算机科学与技术") ; stu.say(); } }
结果:
自我介绍:
姓名:张三
性别:男
年龄:22
以下可以发现,子类的学号,和专业并没有输出,
默认调用的父类的say()方法
需要子类重写父类的方法
三、方法的重写
方法的重写是发生的子类对父类的过程中,是在2个类中,和方法重载是在一个类中
方法重写有以下要求
Student类重写Person类中的say()方法
package com.pb.person; /* * 子类 */ public class Student extends Person { private int stuNo ; //学号 private String specialty; //专业 public Student() { } public Student(String name, String sex, int age,int stuNo,String specialty) { super(name, sex, age); this.stuNo=stuNo; this.specialty=specialty; } //方法重写 @Override public void say() { super.say(); System.out.println("学号是:"+this.stuNo); System.out.println("专业是:"+this.specialty); } //getter/setter方法 public int getStuNo() { return stuNo; } public void setStuNo(int stuNo) { this.stuNo = stuNo; } public String getSpecialty() { return specialty; } public void setSpecialty(String specialty) { this.specialty = specialty; } }
测试类不变:
package com.pb.persontest; import com.pb.person.Student; public class Test { public static void main(String[] args) { Student stu=new Student("张三", "男", 22, 121, "计算机科学与技术") ; stu.say(); } }
结果:
自我介绍:
姓名:张三
性别:男
年龄:22
学号是:121
专业是:计算机科学与技术
重写以后,调用的就是子类重写后的方法
四、super关键字
super必须是出现在子类中(子类的方法和构造方法中),而不是其他位置,在构造方法中必须出现在第一行
用以访问父类的成员,例如:父类的属性、方法、构造方法
访问权限的限制,例如无法通过super访问private成员
五、继承条件下构造方法的调用规则
规则一:如果子类的构造方法中没有通过super显示调用父类的有参构造方法,也没有通过this显式调用自身的其他构造方法,则系统会默认先调用父类的无参构造方法
规则二:如果子类的构造方法中通过super显示调用父类的有参构造方法,那将执行父类的相应的构造方法,而不执行父类无参数构造方法
规则三:如果子类的构造方法中通过this显式调用自身的其他构造方法,在相应构造方法中应用以上2条规则
5.1、例一
package compb.demo4; /* * 父类 */ public class StaticSuper { public static String staticGet() { return "父类静态方法"; } public String dynamicGet() { return "父类动态方法"; } } package compb.demo4; /* * 子类 */ public class StaticSub extends StaticSuper{ //静态方法不能重写 public static String staticGet() { return "子类静态方法"; } @Override public String dynamicGet() { return "子类动态方法重写父类动态方法"; } } package compb.demo4; /* * 测试 */ public class Test { public static void main(String[] args) { StaticSub s= new StaticSub(); //声明子类对象 System.out.println(s.staticGet()); //调用子类静态方法 System.out.println(s.dynamicGet()); //调用子类动态方法 } }
结果:
子类静态方法
子类动态方法重写父类动态方法
5.2、例二、
package com.pb.demo5; /* * 父类 */ public class VenderLate { public VenderLate() { System.out.print("VenderLate out"); } } package com.pb.demo5; public class MoveGoods extends VenderLate{ public MoveGoods( ) { System.out.println("MoveGoods out!"); } public MoveGoods(String s) { System.out.println(s); } } package com.pb.demo5; /* * 测试类 */ public class Test { public static void main(String[] args) { MoveGoods m=new MoveGoods(); MoveGoods g=new MoveGoods(" child"); } }
结果:
VenderLate outMoveGoods out!
VenderLate out child
5.3 、例三
package com.pb.demo4; /* * 父类 */ public class SuperClass { private String name; public SuperClass() { System.out.println("父类的无参数构造方法"); } public SuperClass(String name) { System.out.println("父类有一个参数的构造方法:"+name); } //setter/getter方法 public String getName() { return name; } public void setName(String name) { this.name = name; } }
子类
package com.pb.demo4; public class SubClass extends SuperClass { private String name; private int count; public SubClass() { System.out.println("子类无参数构造方法"); } public SubClass(int count) { System.out.println("子类有一个参数构造方法:"+count); } //调用父类有参数的构造方法 public SubClass(String name) { super(name); this.name=name; System.out.println("调用子类有一个参数构造方法,同时使用super显示调用"+name); } //setter/getter方法 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } }
测试类:
package com.pb.demo4; public class Test { public static void main(String[] args) { System.out.println("*******调用子类无参数构造方法**********"); SubClass s1=new SubClass(); System.out.println("*******调用子类有一个参数构造方法但是没有使用super显示调用**********"); SubClass s2=new SubClass(34); System.out.println("*******调用子类有一个参数构造方法,同时使用super显示调用**********"); SubClass s3=new SubClass("张三"); } }
结果:
*******调用子类无参数构造方法********** 父类的无参数构造方法 子类无参数构造方法 *******调用子类有一个参数构造方法但是没有使用super显示调用********** 父类的无参数构造方法 子类有一个参数构造方法:34 *******调用子类有一个参数构造方法,同时使用super显示调用********** 父类有一个参数的构造方法:张三 调用子类有一个参数构造方法,同时使用super显示调用张三
六、Object类
所有的有类都自动继承java.lang包中的Object类
Object类是所有类的父类(基类)
在定义一个类时如果没有使用extends关键字,则默认继承Object类
Object常被重写的方法: