继承和多态
1, 继承
1.1 继承的概念
1.2 继承的格式
1.2.1 在继承关系上"子类就是一个父类",也就是说,子类可以被当做父类使用,
例如:“父类是员工,子类是老师,”老师就是一个员工,他们是 is–a关系
1.2.2 父类定义格式
public class 父类名称{
//…
}
子类定义格式
public class 子类名称 extemds 父类名称{
//…
}
代码实现:
package cn.itcast.day09.demo01;
/**
* 定义一个父类
*/
public class Employee {
public void method(){
System.out.println("方法执行了");
}
}
package cn.itcast.day09.demo01;
/**
* 定义一个员工的子类 老师类
*/
public class Teacher extends Employee {
}
package cn.itcast.day09.demo01;
/**
* 定义一个员工的子类 助教
*/
public class Assistant extends Employee {
}
package cn.itcast.day09.demo01;
public class Demo01Extends {
public static void main(String[] args) {
//创建一个子类对象
Teacher teacher = new Teacher();
teacher.method();//方法执行了
//创建另一个子类对象
Assistant assistant = new Assistant();
assistant.method();//方法执行了
}
}
1.3 继承中成员变量的访问特点
代码实现
package cn.itcast.day09.demo02;
public class Fu {
int numFu = 10;
int num = 100;
public void methodFu(){
System.out.println(num);
}
}
package cn.itcast.day09.demo02;
public class Zi extends Fu{
int numZi = 20;
int num = 200;
public void methodZi(){
System.out.println(num);
}
}
package cn.itcast.day09.demo02;
/**
* 在父子类的成员关系中,如果成员变量重名,则创建子类对象时,访问有两种方式
* 1.直接通过子类对象访问成员变量,
* 等号左边是谁,就优先用谁,没有就向上找。
* 2.间接通过成员方法访问成员变量
* 该方法属于谁就优先用谁没有就向上找。
*/
public class Demo01ExtendsField {
public static void main(String[] args) {
Fu fu = new Fu();//创建父类对象
System.out.println(fu.numFu);//只是创建了父类对象,所以没有子类方法
Zi zi = new Zi();
System.out.println("==================================");
System.out.println(zi.numFu);//10
System.out.println(zi.numZi);//20
System.out.println("========================================");
System.out.println(zi.num);//200等号左边是谁,就优先用谁,没有就向上找。
//System.out.println(zi.abc);//没有找到。编译出错。
System.out.println("=====================================");
//该方法属于谁就优先用谁没有就向上找。
zi.methodZi();//200
//该方法属于谁就优先用谁没有就向上找。
zi.methodFu();//100
}
}
1.4 区分子类变量中3种变量的重名问题
代码实现
package cn.itcast.day09.demo03;
public class Fu {
int num = 10;
}
package cn.itcast.day09.demo03;
public class Zi extends Fu {
int num = 20;
public void method(){
int num = 30;
System.out.println(num);//局部变量
System.out.println(this.num);//本类中的成员变量
System.out.println(super.num);//父类中的成员变量
}
}
package cn.itcast.day09.demo03;
/**
* 局部变量 直接写成员变量名
* 子类中的成员变量 this.成员变量名
* 父类当中的成员变量 super.成员变量名
*/
public class Demo01ExtendsField {
public static void main(String[] args) {
//创建子类对象
Zi zi = new Zi();
zi.method();
}
}
1.5 继承中成员方法的访问特点
代码实现
package cn.itcast.day09.daemo04;
public class Fu {
public void methodFu(){
System.out.println("父类方法执行");
}
public void method(){
System.out.println("父类重名方法执行");
}
}
package cn.itcast.day09.daemo04;
public class Zi extends Fu {
public void methodZi(){
System.out.println("子类方法执行");
}
public void method(){
System.out.println("子类重名方法执行");
}
}
package cn.itcast.day09.daemo04;
/**
* 在父子类的继承关系中,创建子类对象。访问成员方法的规则。
* 创建的对象是谁,就优先用谁。没有就向上找。
* 注意事项:
* 无论是成员变量还是成员方法。如果没有,就是向上找父类,绝不会向下找子类的。
*/
public class Demo01ExtendsMethod {
public static void main(String[] args) {
Zi zi = new Zi();
zi.methodFu();
zi.methodZi();
//创建的是new了的子类的对象。所以优先向上找。
zi.method();
}
}
1.6 继承中方法的覆盖重写概念
重写(Override) :在继承关系当中,方法的名称一样,参数列表也一样。又称为覆盖,覆写。
重载(Overload)方法的名称相同,参数列表不同。
方法覆盖重写的特点:创建的是子类对象,则优先用子类方法。
1.7 继承中方法覆盖重写的注意事项
1.必须保证父子类之间方法的名称相同。参数列表也相同
@Override 写在方法前面,用来检测是不是正确的覆盖重写。
2.子类方法的返回值必须小于等于父类方法的返回值范围。
小扩展 java.lang.Object类是所有类的公共最高父类(祖宗类)java.lang.String是Object的子类
3.子类方法的权限不许大于等于弗雷方法的权限修饰符。
小扩展:public > protected > (default) >private
default不是关键字,而是什么都不写,留空。
代码实现:
package cn.itcast.day09.demo05;
public class Fu {
Object method(){
return null;
}
}
package cn.itcast.day09.demo05;
public class Zi extends Fu{
@Override
public String method(){
return null;
}
}
package cn.itcast.day09.demo05;
public class Demo01MethodOverRide {
public static void main(String[] args) {
Zi zi = new Zi();
zi.method();
}
}
1.8 继承中方法覆盖重写的应用
代码演示
package cn.itcast.day09.demo06;
//这是一个老款手机
public class Phone {
public void call(){
System.out.println("打电话");
}
public void send(){
System.out.println("发短信");
}
public void show(){
System.out.println("显示号码");
}
}
package cn.itcast.day09.demo06;
//这是一个新款手机
public class NewPhone extends Phone {
@Override
public void show() {
super.show();//把父类的show方法拿过来重复利用
//然后在子类添加更更多内容
System.out.println("显示头像");
System.out.println("显示姓名");
}
}
package cn.itcast.day09.demo06;
public class Demo01Phone {
public static void main(String[] args) {
Phone phone = new Phone();
phone.call();
phone.send();
phone.show();
System.out.println("===============================");
NewPhone newPhone = new NewPhone();
newPhone.call();
newPhone.send();
newPhone.show();
}
}
1.9 继承中构造方法的访问特点
package cn.itcast.day09.demo07;
public class Fu {
public Fu(){
System.out.println("父类构造方法");
}
public Fu(int num){
System.out.println("父类构造方法");
}
}
package cn.itcast.day09.demo07;
public class Zi extends Fu {
public Zi(){
System.out.println("子类构造方法");
}
public Zi(int num){
super(10);//在调用父类重载的构造方法
// super(12)
System.out.println("子类构造方法");
}
public void method(){
//super();只有子类构造方法才能调用父类构造方法
}
}
package cn.itcast.day09.demo07;
/**
* 继承关系中,父子类构造方法的访问特点
* 1.子类构造方法中含有一个隐含的默认super()调用,所以一定是先调用父类构造,再执行子类构造
* 2.子类构造可以通过super关键字调用父类重载构造。
* 3.super的父类构造必须是子类方法的第一个语句,不能是一个子类构造调用多次父类构造。
* 总结:子类必须调用父类构造方法,不写则赠送一个,写了则写了的super()调用,super只能有一个,还必须是第一个。
*/
public class deno01Constructor {
public static void main(String[] args) {
Zi zi = new Zi(20);
}
}
1.10 super关键字的3种用法
1.在子类的成员方法中,访问父类的成员变量。
2.在子类的成员方法中,访问父类的成员方法。
3.在子类的构造方法中,访问父类的构造方法。
代码实现:
package cn.itcast.day09.demo8;
public class Fu {
int num = 10;
public void method(){
System.out.println("父类方法");
}
}
package cn.itcast.day09.demo8;
public class Zi extends Fu {
int num = 20;
public Zi(){
super();//3.在子类的构造方法中,访问父类的构造方法。
}
public void methodZi(){
System.out.println(super.num);//1.在子类的成员方法中,访问父类的成员变量。
}
public void method(){
super.method();//2.在子类的成员方法中,访问父类的成员方法。
System.out.println("父类方法");
}
}
1.11 this关键字的3种用法
super关键字用来访问父类内容,而this关键字用来访问本类内容,用法有3点。
1.在本类的成员方法中,访问本类的成员变量、
2.在本类的成员方法中,访问本类的另一个成员方法.
3.在本类的构造方法中,访问本类的另一个构造方法。
在第三种用法中要注意:
A: this调用也必须是构造方法的第一个一句,且是唯一一个。
B: super和thos两种构造调用,不能同时使用。
代码实现:
package cn.itcast.day09.demp09;
public class Fu {
int num = 30;
}
package cn.itcast.day09.demp09;
public class Zi extends Fu {
int num = 10;
public Zi(){
//super();错误写法
this(10);//本类当中的无参构造调用本类当中的有参构造、
}
public Zi(int num){
this(11,22);
}
public Zi(int num,int num2){
// this();错误写法
}
public void show() {
int mum = 20;
System.out.println(num);//成员变量
System.out.println(this.num);//本类当中的成员变量
System.out.println(super.num);//父类中的成员变量
}
public void methodA(){
System.out.println("aaaaa");
}
public void methodB(){
this.methodA();//调用本类当中的另一个成员方法
System.out.println("bbbbb");
}
}
1.12 super和this关键字图解
1.13 Java继承的3个特点
2. 抽象类
2.1 抽象的概念
一:
二::
概念:如果父类当中的方法不确定如何{}方法体的实现,那么这就应该是一个抽象方法。
2.2 抽象方法和抽象类的定义格式
代码实现:
package cn.itcast.day09.demo11;
/**
* 抽象方法 :就是加上abstract关键字 ,去掉大括号,然后分好结束
* 抽象类:抽象方法所在的类不许是抽象类,但是抽象类中可以有普通的成员方法。
* 格式:在 class 之前加abstract 即可
*/
public abstract class Animal {
//这是一个抽象方法,代表吃东西,但是具体吃什么,不清楚
public abstract void eat();
//这是一个普通成员方法
public void method(){
}
}
2.3 抽象方法和抽象类的使用
1.不能直接使用new抽象类对象。
2.必须用一个子类来继承抽象父类。
3,子类必须覆盖重写父类当中所有的抽象方法。
覆盖重写【实现】子类去掉抽象方法的abstract关键字,然后加上{}方法体
4.创建子类对象进行使用。
代码实现:
package cn.itcast.day09.demo11;
/**
* 抽象方法 :就是加上abstract关键字 ,去掉大括号,然后分好结束
* 抽象类:抽象方法所在的类不许是抽象类,但是抽象类中可以有普通的成员方法。
* 格式:在 class 之前加abstract 即可
*/
public abstract class