赞
踩
父类也叫基类、超类
子类也叫派生类
在继承的而关系中,“子类就是一个父类“。也就是说,子类可以被当做父类来看待。例如父类是员工,子类是老师,那么我们可以说**”老师就是一个员工“**。
public class 父类名称{
//.....
}
public class 子类名称 extends 父类名称{
//.....
}
public class Employee(){
public void method(){
System.out.println("方法执行")
}
}
public class Teacher extends Employee{
//我们先不在里面添加任何东西
}
public class Main {
public static void main(String[] args) {
Teacher one = new Teacher();
//Teacher类继承了Empolyee类的方法
one.method();
}
}
/*输出结果:
执行方法
*/
2.3.4 小结论
Teacher类继承了Employee类,也就继承了它的 public void method() 方法,达到了代码复用的效果,当父类有我们子类需要用的方法时,我们就不用再去重新打一次,直接可以拿来用。
public class Fu {
public int numFu = 10; //关键字为public,可以直接通过(对象.变量名)访问,方便说明问题
}
public class Zi extends Fu{
public int numZi = 20;
}
public class Demo02ExtendsField {
public static void main(String[] args) {
//创建父类对象
Fu fu = new Fu();
//父类只能找到自己的成员numFu,并没有找到子类的成员numZi
System.out.println(fu.numFu);
//创立一个子类对象
Zi zi = new Zi();
//子类对象既可以打印父类的成员numFu,也可以打印自己的成员numZi
//还是那句"先人不知道后人的事情,而后人知道先人的事情"
System.out.println(zi.numFu);
System.out.println(zi.numZi);
}
}
直接通过对象访问成员变量:
等号左边是谁,就优先用谁,没有则向上找
间接通过成员方法访问成员变量
该方法属于谁,就优先用谁,没有则向上找
假设现在父类 Fu 和子类 Zi 都有一个变量名叫num
Fu 类
public class Fu {
public int num = 10;
public void methodFu(){
//这里打印的num,一定是本类的,不会再往下找子类的
System.out.println(num);
}
}
Zi类
public class Zi extends Fu{
public int num = 20;
public void methodZi(){
//这里打印的num,如果本类有,就优先打印本类的,如果没有再往上找
System.out.println(num);
}
}
第一种情况:直接通过对象访问成员变量
等号左边是谁,就优先用谁,没有则向上找。Fu fu = new Zi();
等号的左边是父类
public class Demo02ExtendsField {
public static void main(String[] args) {
// Zi zi = new Fu(); 不能通过父类来构造子类,先人(父类)根本不知道后人(子类)长什么样子
Fu fu = new Zi(); //可以通过子类来构造父类,这时等号左边是父类
System.out.println(fu.num); //10,打印的是父类的num
}
}
第二种情况:间接通过成员方法访问成员变量
public class Demo02ExtendsField { public static void main(String[] args) { Fu fu = new Fu(); Zi zi = new Zi(); //打印的是父类的num,因为该类没有继承其它类,他自己肯定有一个num,才能写出这个方法 fu.methodFu(); //父类的num 10,补充:没有fu.methodZi(), 先人不知道后人的方法 //如果子类有一个num,那就优先打印本类的,没有的话再往父类那里找 zi.methodZi(); //子类的num 20 //重点!子类用的是父类的方法打印num,这就要看这个方法属于谁,是谁定义的这个方法 //因为methodFu()这个方法是属于父类的,打印的当然就是父类的num zi.methodFu(); //父类的num 10 } }
假如有好多个num,父类有一个,子类有两个,怎么才能正确地打印想要的那个num呢?
4.1 父类
public class Fu {
public int num = 10;
}
4.2 子类
public class Zi extends Fu {
public int num = 20;
public void methodZi(){
int num = 30;
System.out.println(num); //30, 局部变量
System.out.println(this.num); //20, 本类的成员变量
System.out.println(super.num);//10, 父类的成员变量
}
}
4.3 看看子类方法 methodZi() 能不能正确区分三个num
public class Demo03Main {
public static void main(String[] args) {
Zi zi = new Zi();
zi.methodZi(); //30, 20, 10
}
}
4.4 总结:要想正确地打印想要的num,可以这样打
假如子类和父类都有一个方法叫 method() , 那怎么知道用的是哪一个呢?
5.1 父类
public class Fu {
public void method(){
System.out.println("父类重名方法执行");
}
}
5.2 子类
public class Zi extends Fu {
public void method(){
System.out.println("子类重名方法执行");
}
}
5.3 在main中调用 method() 方法
public class Demo04Main {
public static void main(String[] args) {
Fu fu1 = new Fu();
Fu fu2 = new Zi(); //通过子类来构造fu2
Zi zi = new Zi();
fu1.method(); //父类重名方法执行, 用的是父类方法
fu2.method(); //子类重名方法执行,用的是子类方法
zi.method(); //子类重名方法执行, 用的是子类方法
}
}
结论 :
Fu fu2 = new Zi();
,fu2是用子类来构造的,那fu2.method()
就是用的子类的方法由 5. 继承中成员方法重名的问题,我们可以引出重写(Override)的概念
重写:在继承关系中,方法的名称一样,参数列表也一样
重写:方法的名称一样,参数列表【也一样】。也叫覆盖、覆写
重载:方法的名称一样,参数列表【不一样】。
6.2.1 必须保证父子类之间方法的名称相同,参数列表也相同,否则无法进行覆盖重写
6.2.2 注解:@Override,这个注解写在方法的前面,用来检验是不是有效的覆盖重写,例如当方法名写错了,@Override底下就会出现红色的波浪线,提示你这不是有效的覆盖重写。
public class Zi extends Fu {
@Override
public void method(){
System.out.println("子类重名方法执行");
}
}
这个注解可写可不写,但是强烈推荐把它写上去。
6.2.3 子类方法的返回值必须【小于等于】父类方法的返回值范围。java.lang.Object是所有类的公共最高父类(祖宗类),每个类都默认继承了它,例如String类就是Object的子类。下面代码会报错,是因为返回值的范围问题
6.2.3.1 父类
public class Fu {
public String method(){
System.out.println("父类重名方法执行");
}
}
6.2.3.2 子类
public class Zi extends Fu {
@Override
public Object method(){ //范围:Object > String 报错
System.out.println("子类重名方法执行");
}
}
6.2.4 子类方法的权限必须【大于等于】父类方法的权限修饰符。权限的排名:public > protected > (default) > private。备注:(default)不是关键字default,而是什么都不写,留空,例如:
public class Fu{
int num; //num的访问权限是default
}
下面的代码会因为重写方法的权限问题而报错:
6.2.4.1 父类
public class Fu {
public void method(){
System.out.println("父类重名方法执行");
}
}
6.2.4.2 子类
public class Zi extends Fu {
@Override
protected void method(){ //protected < public 报错
System.out.println("子类重名方法执行");
}
}
假如旧手机的功能有打电话、发短信、来电显示(显示号码)
新手机的功能有来电显示、发短信、来电显示(显示号码、显示头像、显示姓名)
可见新旧手机的打电话和发短信功能是一样的,但是新手机的来电显示功能比旧手机多了显示头像、显示姓名。
我们可以把旧手机当做父类,把新手机当做子类,新手机只需要重写旧手机的来电显示功能即可
6.3.1 旧手机是父类,名为Oldphone类
public class Oldphone {
//打电话功能
public void call(){
System.out.println("打电话");
}
//发短信功能
public void send(){
System.out.println("发短信");
}
//来电显示功能
public void show(){
System.out.println("显示号码");
}
}
6.3.2 新手机是子类,名为Newphone类
public class Newphone extends Oldphone{
@Override
public void show() {
super.show(); //不要修改原来的代码,直接通过super调用它,后面再添加新的内容
System.out.println("显示头像");
System.out.println("显示姓名");
}
}
6.3.3 在main中实验一下
public class Demo05Main {
public static void main(String[] args) {
Newphone newphone = new Newphone();
newphone.call();
newphone.send();
newphone.show();
}
}
/*输出结果:
打电话
发短信
显示号码
显示头像
显示姓名
*/
子类的构造方法启动时,一定会先跑去启动父类的构造方法,等父类的构造方法执行完后,再去执行子类(本类)的构造方法。
7.2.1 父类(只有无参构造方法)
public class Fu {
//父类的无参构造方法
public Fu(){
System.out.println("父类构造方法执行");
}
}
7.2.2 子类
public class Zi extends Fu {
//子类的无参构造方法
public Zi(){
System.out.println("子类构造方法执行");
}
}
7.2.3 在main中构造一个子类
public class Demo06Main {
public static void main(String[] args) {
Zi zi = new Zi();
}
}
/*输出结果:
父类构造方法执行
子类构造方法执行
*/
7.2.4 小总结
其实子类的构造方法中隐含了super()调用,如果子类的构造方法没有写super(),编译器会帮我们默认加上去。子类就变成
public class Zi extends Fu {
//子类的无参构造方法
public Zi(){
super(); //注意!这句必须写在第一行的位置,如果父类构造函数有参数,就是super(参数),有 参数的调用,必须要自己写上去,不然会默认调用无参构造
System.out.println("子类构造方法执行");
}
}
在子类的成员方法中,访问父类的成员变量,比如:
8.1.1 父类
public class Fu {
public int num = 10;
}
8.1.2 子类
public class Zi extends Fu {
public int num = 20;
public void methodZi(){
// System.out.println(num); 这样打印的一定是本类的num
System.out.println(super.num); //打印的是父类的num
}
}
在子类的成员方法中,访问父类的成员方法,比如:
8.2.1 父类
public class Fu {
public void methodFu(){
System.out.println("父类的成员方法执行");
}
}
8.2.2 子类
public class Zi extends Fu{
public void methodZi(){
super.methodFu(); //访问父类的methodFu()方法
System.out.println("子类的成员方法执行");
}
}
在main中执行子类的方法
public class Demo07Main {
public static void main(String[] args) {
Zi zi = new Zi();
zi.methodZi();
}
}
/*输出结果:
父类的成员方法执行
子类的成员方法执行
*/
在子类的构造方法中,访问父类的构造方法。就在 7. 继承中构造方法的访问特点 中,请自行查阅。
9.1 概述
9.1.1 在本类的成员方法中,访问本类的成员变量
9.1.2 在本类的成员方法中,访问本类的另一个成员方法
9.1.3 在本类的构造方法中,访问本类的另一个构造方法
9.2 代码说明一下
public class Zi extends Fu { private int num = 10; public Zi(){ this(123); //9.1.3 在本类的无参构造中调用有参构造 } public Zi(int num){ this.num = num; } public void methodZi(){ System.out.println(this.num); //9.1.1 在本类的成员方法中,访问本类的成员变量 } public void methodA(){ System.out.println("A方法"); } public void methodB(){ this.methodA(); //9.1.2 在本类的成员方法中,访问本类的另一个成员方法 System.out.println("B方法");
9.3 注意事项
10.1 java语言是单继承的
一个类的直接父类只能有唯一的一个。
class A{}
class B extends A{} 正确写法
class C{}
class D extends A,C{} 错误写法,不能同时继承A和C
试想假如class A{}有一个 method() 方法,
Class C{}也有一个 method() 方法,
子类D同时继承类A和类C,那当我新建一个D类对象d后,
对象d想要调用父类的method方法,那它应该用A的 method() 还是C的 method() 呢?这就乱套了!
10.2 java语言是可以多级继承的
虽然,java语言是单继承的,一个类的直接父类只有一个,类D不能同时继承类A和类C
但是,可以让类A继承类C之后,类D再继承类A,C就是爷爷,A就是爸爸,D就是儿子
类D --> 类A --> 类C,这就叫多级继承。
10.3 java语言中,一个父类可以有多个子类
这就好比二胎政策,一个爸爸可以有多个儿子
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。