第四课时 继承
纲要:1.继承
2.方法重写
3.自动转型
一.生活中的继承
例:鸟是一个种类,
啄木鸟是鸟的一种,啄木鸟有一个区别于其他鸟的地方就是会消灭树皮下的害虫,
因此在鸟的基础上加上一个会消灭树中的害虫这条行为就可以衍生出啄木鸟类。
啄木鸟和鸟之间就有继承关系,
其中啄木鸟就是子类,鸟就是父类。
二.Java中继承的语法格式:
继承的关键字是:extends
格式:
public class 类名(子类、超类、派生类)extends 类名(父类、基类) {
}
三.子类可以继承到父类的哪些属性和方法:
1. 子类可以继承到父类所有的属性和方法,
但是根据其访问限定符的不同而有不同的访问权限。
2. 访问限定符有以下几种:public
protected
默认
private
(访问限定符范围:public>protected>默认>private)
3. 子类和父类不在同一包下:
子类中只可以调用限定符为public和protected的方法和属性,
子类对象只可以调用限定符为public的方法和属性。
子类和父类在同一包下:
子类和子类对象都可以调用除限定符为private的方法和属性。
四.继承的实例:
1.子类与父类在同一包下:
- //定义一个student类
- public class student {
- private String name; //学生的姓名属性
- /**
- * 设置学生名字的方法,访问限定符为public
- * @param n 学生的名字参数
- */
- public void setName(String name){
- this.name=name;
- }
- /**
- * 获取学生名字的方法,访问限定符为protected
- * @return 学生的名字
- */
- protected String getName(){
- return name;
- }
- /**
- * 学生学习的方法,使用默认的访问限定符,
- */
- void study(){
- System.out.println("学生学习中!");
- }
- }
//定义一个student类
public class student {
private String name; //学生的姓名属性
/**
* 设置学生名字的方法,访问限定符为public
* @param n 学生的名字参数
*/
public void setName(String name){
this.name=name;
}
/**
* 获取学生名字的方法,访问限定符为protected
* @return 学生的名字
*/
protected String getName(){
return name;
}
/**
* 学生学习的方法,使用默认的访问限定符,
*/
void study(){
System.out.println("学生学习中!");
}
}
- //定义一个大学生类UNStudent,继承学生类
- public class UNStudent extends student {
- }
//定义一个大学生类UNStudent,继承学生类
public class UNStudent extends student {
}
- //定义一个管理员类
- public class Manger{
- //主函数的入口
- public static void main(String [] args){
- //实例化一个大学生类
- UNStudent un=new UNStudent();
- //大学生继承了学生类的设置姓名方法,在同一包下且为public,所以可以设置大学生的姓名
- un.setName("大学生");
- //大学生类继承了学生类的获取姓名的方法,在同一包下且为protected,所以可以获取大学生的姓名
- String n=un.getName();
- //输出大学生的姓名
- System.out.println(n);
- //大学生类继承了学生类的学习方法,在同一包下且为默认访问符,所以可以调用学习的方法
- un.study();
- //大学生继承了学生类,但是姓名属性为private,为父类所特有,不能被子类访问到
- //un.name;
- }
- }
//定义一个管理员类
public class Manger{
//主函数的入口
public static void main(String [] args){
//实例化一个大学生类
UNStudent un=new UNStudent();
//大学生继承了学生类的设置姓名方法,在同一包下且为public,所以可以设置大学生的姓名
un.setName("大学生");
//大学生类继承了学生类的获取姓名的方法,在同一包下且为protected,所以可以获取大学生的姓名
String n=un.getName();
//输出大学生的姓名
System.out.println(n);
//大学生类继承了学生类的学习方法,在同一包下且为默认访问符,所以可以调用学习的方法
un.study();
//大学生继承了学生类,但是姓名属性为private,为父类所特有,不能被子类访问到
//un.name;
}
}
2.子类与父类不在同一包下
- //定义一个student类
- public class student {
- private String name; //学生的姓名属性
- /**
- * 设置学生名字的方法,访问限定符为public
- * @param n 学生的名字参数
- */
- public void setName(String name){
- this.name=name;
- }
- /**
- * 获取学生名字的方法,访问限定符为protected
- * @return 学生的名字
- */
- protected String getName(){
- return name;
- }
- /**
- * 学生学习的方法,使用默认的访问限定符。
- */
- void study(){
- System.out.println("学生学习中!");
- }
- }
//定义一个student类
public class student {
private String name; //学生的姓名属性
/**
* 设置学生名字的方法,访问限定符为public
* @param n 学生的名字参数
*/
public void setName(String name){
this.name=name;
}
/**
* 获取学生名字的方法,访问限定符为protected
* @return 学生的名字
*/
protected String getName(){
return name;
}
/**
* 学生学习的方法,使用默认的访问限定符。
*/
void study(){
System.out.println("学生学习中!");
}
}
- //定义一个大学生类UNStudent,继承学生类
- public class UNStudent extends student {
- //在类中调用父类的方法和属性
- public void call(){
- //在类中实例化一个大学生类
- UNStudent un=new UNStudent();
- //子类和父类不在同一包下,方法为public限定符,可以在子类中被调用
- un.setName("大学生1号");
- //子类和父类不在同一包下,方法为protected限定符,所以也可以在子类中被调用
- un.getName();
- //子类和父类不在同一包下,方法为默认限定符,不可以在子类中被调用
- //un.study();
- //子类和父类不在同一包下,方法为private限定符,不可以在子类中被调用
- //un.name;
- }
- }
//定义一个大学生类UNStudent,继承学生类
public class UNStudent extends student {
//在类中调用父类的方法和属性
public void call(){
//在类中实例化一个大学生类
UNStudent un=new UNStudent();
//子类和父类不在同一包下,方法为public限定符,可以在子类中被调用
un.setName("大学生1号");
//子类和父类不在同一包下,方法为protected限定符,所以也可以在子类中被调用
un.getName();
//子类和父类不在同一包下,方法为默认限定符,不可以在子类中被调用
//un.study();
//子类和父类不在同一包下,方法为private限定符,不可以在子类中被调用
//un.name;
}
}
- //定义一个manger类
- public class manger {
- /**
- * 程序主函数入口
- */
- public static void main(String [] args){
- //实例化一个大学生类
- UNStudent s=new UNStudent();
- //大学生继承了学生类的设置姓名方法,在不同包下但为public,所以对象可以设置大学生的姓名
- s.setName("大学生2号");
- //大学生类继承了学生类的获取姓名的方法,为protected但不在同一包下,所以不能被对象调用
- //String n=s.getName();
- //大学生类继承了学生类的学习方法,为默认访问符但不在同一包下,所以不能被对象调用
- // s.study();
- //大学生继承了学生类,但是姓名属性为private,为父类所特有,不能被子类访问到
- //un.name;
- }
- }
//定义一个manger类
public class manger {
/**
* 程序主函数入口
*/
public static void main(String [] args){
//实例化一个大学生类
UNStudent s=new UNStudent();
//大学生继承了学生类的设置姓名方法,在不同包下但为public,所以对象可以设置大学生的姓名
s.setName("大学生2号");
//大学生类继承了学生类的获取姓名的方法,为protected但不在同一包下,所以不能被对象调用
//String n=s.getName();
//大学生类继承了学生类的学习方法,为默认访问符但不在同一包下,所以不能被对象调用
// s.study();
//大学生继承了学生类,但是姓名属性为private,为父类所特有,不能被子类访问到
//un.name;
}
}
五.方法重写:在子类中重新定义或扩写父类的方法。
1.什么情况下要使用方法重写?
子类和父类有相同的方法,但是父类中的实现方法无法满足子类需要时使用。
例如:手机是父类,步步高音乐手机是子类,
步步高是专门的音乐手机,普通手机的音乐功能自然不能满足该手机的需要,
那么,对于步步高手机来说,
就必须的重写音乐部分的功能,来实现更好的音乐目标。
2.方法重写的条件:(1)有继承关系
(2)子类和父类的返回值类型、方法名以及参数名要一致,
子类访问限定符要大于等于父类的访问限定符范围,
子类的方法体和父类的不同。
3.重写后的方法是如何调用的?
实例化子类对象后,该对象会先在子类中寻找方法,
若找到了,则直接调用子类的方法而不会去调用父类的方法,
若没找到才会调用父类中的方法。
4.方法重写的实例:
- //定义一个student类
- public class student {
- private String name; //学生的姓名属性
- /**
- * 设置学生名字的方法
- * @param n 学生的名字参数
- */
- public void setName(String name){
- this.name=name;
- }
- /**
- * 获取学生名字的方法
- * @return 学生的名字
- */
- protected String getName(){
- return name;
- }
- /**
- * 学生学习的方法,使用默认的访问限定符
- */
- void study(){
- System.out.println("学生学习中!");
- }
- }
//定义一个student类
public class student {
private String name; //学生的姓名属性
/**
* 设置学生名字的方法
* @param n 学生的名字参数
*/
public void setName(String name){
this.name=name;
}
/**
* 获取学生名字的方法
* @return 学生的名字
*/
protected String getName(){
return name;
}
/**
* 学生学习的方法,使用默认的访问限定符
*/
void study(){
System.out.println("学生学习中!");
}
}
- //定义一个大学生类UNStudent,继承学生类
- public class UNStudent extends student {
- //方法重写,重写study方法,访问限定符public大于默认限定符
- public void study(){
- System.out.println("大学生努力学习,认真刻苦!");
- }
- }
//定义一个大学生类UNStudent,继承学生类
public class UNStudent extends student {
//方法重写,重写study方法,访问限定符public大于默认限定符
public void study(){
System.out.println("大学生努力学习,认真刻苦!");
}
}
- //定义一个manger类
- public class manger {
- /**
- * 程序主函数入口
- */
- public static void main(String [] args){
- //实例化一个大学生类
- UNStudent s=new UNStudent();
- //大学生继承了学生类的设置姓名方法,没有被重写,调用的是父类的设置姓名的方法
- s.setName("大学生");
- //用父类获取姓名的方法,输出姓名
- System.out.println("姓名为:"+s.getName());
- //大学生类重写了学习方法,所以不调用父类的学习方法
- s.study();
- }
- }
//定义一个manger类
public class manger {
/**
* 程序主函数入口
*/
public static void main(String [] args){
//实例化一个大学生类
UNStudent s=new UNStudent();
//大学生继承了学生类的设置姓名方法,没有被重写,调用的是父类的设置姓名的方法
s.setName("大学生");
//用父类获取姓名的方法,输出姓名
System.out.println("姓名为:"+s.getName());
//大学生类重写了学习方法,所以不调用父类的学习方法
s.study();
}
}
六.自动转型
1.什么情况下要使用自动转型?
在方法重载的时候,若只有参数类型(类类型)不一样,
且这些类又有相同的父类,这时我们就可以使用自动转型,
通过自动转型,我们只需要写一种方法,这个方法的参数就是父类类型。
当我们用子类对象作为参数使用这个方法的时候,
子类对象就会自动转型为父类类型。
例如:已知一个比武的方法,
可能用弓箭类来比试,也可能用剑来比试,也可能用刀来比试,
弓箭,剑,刀是属于不同的类,我们就要写三种不同的方法。
但是弓箭,剑,刀都是武器类,
我们可以直接定义一个用武器比武的方法,
那么不管是用弓箭、剑还是刀都可以使用这个方法来实现比武。
2.自动转型格式及调用方法
2.1显示格式:父类名 对象名=new 子类构造方法();
2.2隐式调用:
定义: public 返回值类型 方法名(父类名 对象名){
对象名.方法名;
}
调用: 父类名 对象名1=new 子类构造方法();
子类名 对象名2=new 子类构造方法();
方法名(对象名1);
方法名(对象名2);
3.自动转型的实例:
- //定义一个student类
- public class student {
- private String name; //学生的姓名属性
- /**
- * 设置学生名字的方法
- * @param n 学生的名字参数
- */
- public void setName(String name){
- this.name=name;
- }
- /**
- * 获取学生名字的方法
- * @return 学生的名字
- */
- public String getName(){
- return name;
- }
- /**
- * 学生学习的方法,默认的访问限定符,
- */
- public void study(){
- System.out.println("学生学习中!");
- }
- }
//定义一个student类
public class student {
private String name; //学生的姓名属性
/**
* 设置学生名字的方法
* @param n 学生的名字参数
*/
public void setName(String name){
this.name=name;
}
/**
* 获取学生名字的方法
* @return 学生的名字
*/
public String getName(){
return name;
}
/**
* 学生学习的方法,默认的访问限定符,
*/
public void study(){
System.out.println("学生学习中!");
}
}
- //定义一个大学生类UNStudent,继承学生类
- public class UNStudent extends student {
- //方法重写,重写大学生的study方法
- public void study(){
- System.out.println("大学生努力学习,认真刻苦!");
- }
- }
//定义一个大学生类UNStudent,继承学生类
public class UNStudent extends student {
//方法重写,重写大学生的study方法
public void study(){
System.out.println("大学生努力学习,认真刻苦!");
}
}
- //定义一个中学生类MStudent,继承学生类
- public class MStudent extends student {
- //方法重写,重写中学生的study方法
- public void study(){
- System.out.println("中学生的学习方法!");
- }
- }
//定义一个中学生类MStudent,继承学生类
public class MStudent extends student {
//方法重写,重写中学生的study方法
public void study(){
System.out.println("中学生的学习方法!");
}
}
- //定义一个teacher类
- public class teacher {
- //教授学生的方法,参数为基类student类
- public void teach(student st){
- st.study();
- System.out.println("老师给学生上课,这位学生的名字为"+st.getName());
- }
- //程序主函数入口
- public static void main(String [] args){
- //用大学生构造函数实例化一个学生类对象,显性使用自动转型调
- student stu=new UNStudent();
- //设置大学生的名字
- stu.setName("大学生");
- //实例化一个中学生类
- MStudent mid=new MStudent();
- //设置中学生姓名
- mid.setName("中学生");
- //实例化老师累对象
- teacher t=new teacher();
- //对象t调用teach方法,用已经自动转型后的大学生类对象作为参数
- t.teach(stu);
- //对象t调用teach方法,用中学生类对象作为参数,隐性使用自动转型
- t.teach(mid);
- }
- }
//定义一个teacher类
public class teacher {
//教授学生的方法,参数为基类student类
public void teach(student st){
st.study();
System.out.println("老师给学生上课,这位学生的名字为"+st.getName());
}
//程序主函数入口
public static void main(String [] args){
//用大学生构造函数实例化一个学生类对象,显性使用自动转型调
student stu=new UNStudent();
//设置大学生的名字
stu.setName("大学生");
//实例化一个中学生类
MStudent mid=new MStudent();
//设置中学生姓名
mid.setName("中学生");
//实例化老师累对象
teacher t=new teacher();
//对象t调用teach方法,用已经自动转型后的大学生类对象作为参数
t.teach(stu);
//对象t调用teach方法,用中学生类对象作为参数,隐性使用自动转型
t.teach(mid);
}
}
七.多态
多态就是类的多种表现方式,具体表现在方法重载和继承。
八.总结:程序中为什么要用到继承?
1.提高代码的重用性
2.提高程序的扩展性