1.多态
1.1多态的概述(记忆)
-
什么是多态
同一个对象,在不同时刻表现出来的不同形态
-
多态的前提
- 要有继承或实现关系
- 要有方法的重写
- 要有父类引用指向子类对象
1.2多态中的成员访问特点(记忆)
-
成员访问特点
-
成员变量
编译看父类,运行看父类
-
成员方法
编译看父类,运行看子类
-
-
代码演示
-
动物类
public class Animal { public int age = 40; public void eat() { System.out.println("动物吃东西"); } }
-
猫类
public class Cat extends Animal { public int age = 20; public int weight = 10; @Override public void eat() { System.out.println("猫吃鱼"); } public void playGame() { System.out.println("猫捉迷藏"); } }
-
测试类
public class AnimalDemo { public static void main(String[] args) { //有父类引用指向子类对象 Animal a = new Cat(); System.out.println(a.age); // System.out.println(a.weight); a.eat(); // a.playGame(); } }
-
1.3多态的好处和弊端(记忆)
-
好处
提高程序的扩展性。定义方法时候,使用父类型作为参数,在使用的时候,使用具体的子类型参与操作
-
弊端
不能使用子类的特有成员
为什么?
因为多态中调用成员方法的规则是编译看左边,运行看右边,编译时,由于父类没有子类的特有方法,所以编译报错
1.4多态中的转型(应用)
-
向上转型
父类引用指向子类对象就是向上转型
应用场景:在多态方式创建对象的时候
-
向下转型
格式:子类型 对象名 = (子类型)父类引用;
应用场景:多态中使用特有功能的时候
-转型的注意事项
向上转型和向下转型只能是子父类之间的转换,不能用两个子类相互转换
间接多态-----> 爷爷 y = new 儿子();
-
代码演示
- 动物类
public class Animal { public void eat() { System.out.println("动物吃东西"); } }
- 猫类
public class Cat extends Animal { @Override public void eat() { System.out.println("猫吃鱼"); } public void playGame() { System.out.println("猫捉迷藏"); } }
- 测试类
public class AnimalDemo { public static void main(String[] args) { //多态 //向上转型 Animal a = new Cat(); a.eat(); // a.playGame(); //向下转型 Cat c = (Cat)a; c.eat(); c.playGame(); } }
1.5多态的案例(应用)
-
案例需求
请采用多态的思想实现猫和狗的案例,并在测试类中进行测试
-
代码实现
- 动物类
public class Animal { private String name; private int age; public Animal() { } public Animal(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public void eat() { System.out.println("动物吃东西"); } }
- 猫类
public class Cat extends Animal { public Cat() { } public Cat(String name, int age) { super(name, age); } @Override public void eat() { System.out.println("猫吃鱼"); } }
- 狗类
public class Dog extends Animal { public Dog() { } public Dog(String name, int age) { super(name, age); } @Override public void eat() { System.out.println("狗吃骨头"); } }
- 测试类
public class AnimalDemo { public static void main(String[] args) { //创建猫类对象进行测试 Animal a = new Cat(); a.setName("加菲"); a.setAge(5); System.out.println(a.getName() + "," + a.getAge()); a.eat(); a = new Cat("加菲", 5); System.out.println(a.getName() + "," + a.getAge()); a.eat(); } }
2.抽象类
2.1抽象类的概述(理解)
当我们在做子类共性功能抽取时,有些方法在父类中并没有具体的体现,这个时候就需要抽象类了!
在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类!
2.2抽象类的特点(记忆)
-
抽象类和抽象方法必须使用 abstract 关键字修饰
//抽象类的定义 public abstract class 类名 {} //抽象方法的定义 public abstract void eat();
-
抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
-
抽象类不能实例化
抽象类如何实例化呢?参照多态的方式,通过子类对象实例化,这叫抽象类多态
-
抽象类的子类
要么重写抽象类中的所有抽象方法
要么是抽象类
2.3抽象类的成员特点(记忆)
-
成员的特点
- 成员变量
- 既可以是变量
- 也可以是常量
- 构造方法
- 空参构造
- 有参构造
- 成员方法
- 抽象方法
- 普通方法
- 成员变量
-
代码演示
- 动物类
public abstract class Animal { private int age = 20; private final String city = "北京"; public Animal() {} public Animal(int age) { this.age = age; } public void show() { age = 40; System.out.println(age); // city = "上海"; System.out.println(city); } public abstract void eat(); }
- 猫类
public class Cat extends Animal { @Override public void eat() { System.out.println("猫吃鱼"); } }
- 测试类
public class AnimalDemo { public static void main(String[] args) { Animal a = new Cat(); a.eat(); a.show(); } }
2.4抽象类的案例(应用)
-
案例需求
请采用抽象类的思想实现猫和狗的案例,并在测试类中进行测试
-
代码实现
- 动物类
public abstract class Animal { private String name; private int age; public Animal() { } public Animal(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public abstract void eat(); }
- 猫类
public class Cat extends Animal { public Cat() { } public Cat(String name, int age) { super(name, age); } @Override public void eat() { System.out.println("猫吃鱼"); } }
- 狗类
public class Dog extends Animal { public Dog() { } public Dog(String name, int age) { super(name, age); } @Override public void eat() { System.out.println("狗吃骨头"); } }
- 测试类
public class AnimalDemo { public static void main(String[] args) { //创建对象,按照多态的方式 Animal a = new Cat(); a.setName("加菲"); a.setAge(5); System.out.println(a.getName()+","+a.getAge()); a.eat(); System.out.println("--------"); a = new Cat("加菲",5); System.out.println(a.getName()+","+a.getAge()); a.eat(); } }
3.接口
3.1接口的概述(理解)
接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用。
Java中的接口更多的体现在对行为的抽象!
3.2接口的特点(记忆)
-
接口用关键字interface修饰
public interface 接口名 {}
-
类实现接口用implements表示
public class 类名 implements 接口名 {}
-
接口不能实例化
接口如何实例化呢?参照多态的方式,通过实现类对象实例化,这叫接口多态。
多态的形式:具体类多态,抽象类多态,接口多态。
-
接口的子类
要么重写接口中的所有抽象方法
要么子类也是抽象类
3.3接口的成员特点(记忆)
-
成员特点
-
成员变量
只能是常量
默认修饰符:public static final -
构造方法
没有,因为接口主要是扩展功能的,而没有具体存在
-
成员方法
只能是抽象方法
默认修饰符:public abstract
关于接口中的方法,JDK8和JDK9中有一些新特性,后面再讲解
-
-
代码演示
- 接口
public interface Inter { public int num = 10; public final int num2 = 20; // public static final int num3 = 30; int num3 = 30; // public Inter() {} // public void show() {} public abstract void method(); void show(); }
- 实现类
public class InterImpl extends Object implements Inter { public InterImpl() { super(); } @Override public void method() { System.out.println("method"); } @Override public void show() { System.out.println("show"); } }
- 测试类
public class InterfaceDemo { public static void main(String[] args) { Inter i = new InterImpl(); // i.num = 20; System.out.println(i.num); // i.num2 = 40; System.out.println(i.num2); System.out.println(Inter.num); } }
3.4接口的案例(应用)
-
案例需求
对猫和狗进行训练,他们就可以跳高了,这里加入跳高功能。
请采用抽象类和接口来实现猫狗案例,并在测试类中进行测试。
-
代码实现
- 动物类
public abstract class Animal { private String name; private int age; public Animal() { } public Animal(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public abstract void eat(); }
- 跳高接口
public interface Jumpping { public abstract void jump(); }
- 猫类
public class Cat extends Animal implements Jumpping { public Cat() { } public Cat(String name, int age) { super(name, age); } @Override public void eat() { System.out.println("猫吃鱼"); } @Override public void jump() { System.out.println("猫可以跳高了"); } }
- 测试类
public class AnimalDemo { public static void main(String[] args) { //创建对象,调用方法 Jumpping j = new Cat(); j.jump(); System.out.println("--------"); Animal a = new Cat(); a.setName("加菲"); a.setAge(5); System.out.println(a.getName()+","+a.getAge()); a.eat(); // a.jump(); a = new Cat("加菲",5); System.out.println(a.getName()+","+a.getAge()); a.eat(); System.out.println("--------"); Cat c = new Cat(); c.setName("加菲"); c.setAge(5); System.out.println(c.getName()+","+c.getAge()); c.eat(); c.jump(); } }
3.5类和接口的关系(记忆)
-
类与类的关系
继承关系,只能单继承,但是可以多层继承
-
类与接口的关系
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
-
接口与接口的关系
继承关系,可以单继承,也可以多继承
3.6抽象类和接口的区别(记忆)
-
成员区别
-
抽象类
变量,常量;有构造方法;有抽象方法,也有非抽象方法
-
接口
常量;抽象方法
-
-
关系区别
-
类与类
继承,单继承
-
类与接口
实现,可以单实现,也可以多实现
-
接口与接口
继承,单继承,多继承
-
-
设计理念区别
-
抽象类
对类抽象,包括属性、行为
-
接口
对行为抽象,主要是行为
-
4.综合案例
4.1案例需求(理解)
我们现在有乒乓球运动员和篮球运动员,乒乓球教练和篮球教练。
为了出国交流,跟乒乓球相关的人员都需要学习英语。
请用所学知识分析,这个案例中有哪些具体类,哪些抽象类,哪些接口,并用代码实现。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pEBmY6qk-1650201128668)(img\01.png)]
4.2代码实现(应用)
- 抽象人类
public abstract class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public abstract void eat();
}
- 抽象运动员类
public abstract class Player extends Person {
public Player() {
}
public Player(String name, int age) {
super(name, age);
}
public abstract void study();
}
- 抽象教练类
public abstract class Coach extends Person {
public Coach() {
}
public Coach(String name, int age) {
super(name, age);
}
public abstract void teach();
}
- 学英语接口
public interface SpeakEnglish {
public abstract void speak();
}
- 蓝球教练
public class BasketballCoach extends Coach {
public BasketballCoach() {
}
public BasketballCoach(String name, int age) {
super(name, age);
}
@Override
public void teach() {
System.out.println("篮球教练教如何运球和投篮");
}
@Override
public void eat() {
System.out.println("篮球教练吃羊肉,喝羊奶");
}
}
- 乒乓球教练
public class PingPangCoach extends Coach implements SpeakEnglish {
public PingPangCoach() {
}
public PingPangCoach(String name, int age) {
super(name, age);
}
@Override
public void teach() {
System.out.println("乒乓球教练教如何发球和接球");
}
@Override
public void eat() {
System.out.println("乒乓球教练吃小白菜,喝大米粥");
}
@Override
public void speak() {
System.out.println("乒乓球教练说英语");
}
}
- 乒乓球运动员
public class PingPangPlayer extends Player implements SpeakEnglish {
public PingPangPlayer() {
}
public PingPangPlayer(String name, int age) {
super(name, age);
}
@Override
public void study() {
System.out.println("乒乓球运动员学习如何发球和接球");
}
@Override
public void eat() {
System.out.println("乒乓球运动员吃大白菜,喝小米粥");
}
@Override
public void speak() {
System.out.println("乒乓球运动员说英语");
}
}
- 篮球运动员
public class BasketballPlayer extends Player {
public BasketballPlayer() {
}
public BasketballPlayer(String name, int age) {
super(name, age);
}
@Override
public void study() {
System.out.println("篮球运动员学习如何运球和投篮");
}
@Override
public void eat() {
System.out.println("篮球运动员吃牛肉,喝牛奶");
}
}
**
多态 //(☆☆☆☆☆)
一、多态的概述
“同一个对象”,在不同时刻表现出来的"不同形态"
举例:猫是猫 猫是动物
//回顾:
Student s1 = new Student();
//在上面的这行代码中,正在的对象是谁? new Student()
//s1其实仅仅是一个变量
//Student是接收的类型
Person p1 = new Student();
//为什么可以用Person来接收Student的对象? 因为Person的范围比Student大,Person可以是学生、也可以是老师、也可以是工人、农民
//因为Person是Student的父类,父类可以有多个子类,而Student只是Person的其中一个子类。所以Person的范围大于Student
举例:
int i = 10;
long l = i; //自动类型转换
//总结:不管Student s1 = new Student()还是Person p1 = new Student(),真正的对象都是new Student(),只不过,在第一种情况下,学生是以Student形态体现出来的(这个时候虚拟机会认为这个是学生形态)
//第二种方式,学生对象是以Person的形态体现出来的(这个时候虚拟机会认为学生对象是Person形态)
简单来说:多态就是将同一个对象赋值给不同的数据类型
二、多态的前提条件有哪些
*要有继承/实现关系
*要有方法重写
*要有父类引用指向子类对象
Fu f = new Zi(); //(☆☆☆☆☆)
三、多态中成员访问特点
成员:指的是类的成员
// Fu f = new Zi();
1.成员变量
int age = f.age;
编译看左边,运行看左边
//编译看左边,这里的左边到底看什么? 看父类里面有没有你访问的这个成员变量,如果没有就报错
//运行看左边,这里的左边时什么意思? 取得值时父类得成员变量值
2.构造方法
子类初始化时,需要先完成父类的初始化
3.成员方法
编译看左边,运行看右边
//编译看左边,这里得左边是什么意思? 看父类里面有没有你访问的这个成员方法,如果没有就报错
//运行看右边,这里得右边是什么意思? 运行得是子类重写得那个成员方法
举例:孔子装爹
class 孔子爹{
int age = 50;
public void teach(){
System.out.println("教Java")
}
}
-------------------------------------------------
class 孔子 extends 孔子爹{
int age = 20;
public void teach(){
System.out.println("教论语")
}
}
----------------------------------------------------
class Test1{
public static void main(String[] args) {
孔子爹 kzd = new 孔子(); //真正得对象是孔子 体现出来得形态是孔子爹 孔子穿上他老爹得衣服,沾上他老爹得胡子,戴上它老爹得老花镜
int age = kzd.age; //50
kzd.teach(); //教论语
}
}
四、多态得好处和弊端
1.好处:
提高了代码得扩展性
2.弊端
不能使用子类得特有功能
//因为多态中调用成员方法得规则是:编译看左边,运行看右边 看左边得时候,由于父类中没有子类得特有方法,就编译报错了
五、多态中得转型
1.向上转型
上:父类
向上:转成父类
格式:
Fu f = new Zi(); //向上转型,是将子类得对象,转成了父类得类型
long l = 10; //自动类型转换
应用场景:
在使用多态创建对象得时候
*多态的向上转型有以下几种常见的格式:
1.父类类型 对象名 = 子类对象;
2.父类类型 对象名 = (父类类型)子类对象;
3.接口类型 对象名 = 实现类对象;
4.接口类型 对象名 = (接口类型)实现类对象;
2.向下转型
下:子类
向下:转成子类
格式:
Zi zi = (Zi)f //向下转型
int i = 100L; //强制类型转换
应用场景:
多态中需要使用子类特有功能得时候
3.转型得注意事项
向上转型和向下转型只能是子父类之间得转换,不能用两个子类相互转换
举例:
Animal cat = new Cat();
Animal dog = new Dog();
Dog d = (Dog)cat; //报错,因为多态中得转型只能是子类和父类之间得相互转换,两个子类之间绝对不能相互转
六、多态版得猫狗案例
想使用多态就要知道使用多态得前提
*有继承关系
父类 :Animal
public class Animal {
private String name;
private int age;
//构造方法
//get和set方法
public void eat(){
System.out.println("动物吃东东");
}
子类:Cat Dog
public class Dog extends Animal {
public Dog() {
}
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("狗吃肉");
}
}
*有方法重写
Animal:eat
Cat Dog :重写 eat方法
*父类引用指向子类对象、
在测试类中使用
public class Demo1 {
public static void main(String[] args) {
Animal a1 = new Dog();
a1.setName("二哈");
a1.setAge(1);
a1.eat();
System.out.println(a1.getName()+"==="+a1.getAge());
Animal a2 = new Dog("三哈",2);
a2.eat();
System.out.println(a2.getName()+"==="+a2.getAge());
}
}
抽象类 //(☆☆☆☆☆)
一、抽象类的概述
1.抽象是什么意思?
不是具体的、看不懂的
2.Java中抽象的引入
在多态中,调用成员方法的时候,规则是编译看左边,运行看右边,左边的父类中定义的方法,它的方法体永远都不会被执行,这个时候有人就想把这个方法体去掉
就引入了abstract抽象的概念
3.在Java中怎么表示抽象
关键字:
abstract : 被赋予的特殊含义是表示抽象的 可以修饰类和方法 //abstract是抽象的标志
4.抽象类和方法的格式
(1)抽象方法
public abstract void eat();
(2)抽象类
public abstract class 类名{
}
二、抽象类的特点//☆☆☆☆☆
1.抽象类和抽象方法必须使用abstract关键字修饰 //abstract是抽象的标志
public abstract class 类名{}
public abstract 返回值类型 方法名(); //抽象方法是没有大括号方法体的
2.抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类 //常见你的单选题
3.抽象类不能实例化,但是可以通过多态的方式创建子类对象
//为什么抽象类不能直接被初始化?
//因为一个类如果是抽象类,那么里面很有可能有抽象方法,而抽象方法是没有方法体得,你创建对象调用抽象方法一点意义都没有
4.抽象类的子类
要么重写抽象父类中"所有的"抽象方法 //推荐使用
要么子类本身也是一个抽象类 //一般出现在源码中
5.抽象类得本质
其实就是用来替代父类得
三、抽象类中得成员特点
1.成员变量
可以是变量
可以是常量
2.构造方法
有构造方法
//用来子类初始化是,先完成父类(抽象类)得初始化
3.成员方法
可以是非抽象方法
可以是抽象方法:强制要求子类取重写的
四、多态的分类 //截止到目前为止
1.父类是一个普通类的多态
2.父类是一个抽象类的多态
接口 //(☆☆☆☆☆)
一、接口的概述
接口就是一种 "公共的"(public) 规范标准,只要符合规范标准,都可以使用
java中的接口更多的体现在对 "行为"(方法) 的抽象
二、接口的特点
1.如何定义接口
public interface 接口名{}
* interface关键字 :特殊含义是告诉虚拟机(JVM)我是在定义一个接口,后面跟的是接口的名称,后面的大括号是接口的范围
*在idea中怎么创建一个接口
和创建类一样,只不过在选择kind选项的时候要选择Interface
2.如何实现接口
public class 类名 implements 接口名{}
*类实现了接口,而接口是一个规范,所以在这里接口就是用来规范类的
* implements关键字 : 特殊含义是表明是一个类在实现接口
3.接口不能被实例化,可以通过多态形式创建实现类对象
*接口多态 //用的最多
MyInter mi = new Student(); //称MyInter是Student的干爹
*抽象类多态 //父类是一个抽象类
Animal a = new Dog(); //称Animal是Dog的亲爹
//注意:接口和实现类之间是没有继承关系的,是实现关系
*具体类多态 //父类是一个具体类
4.接口的实现类
要么重写接口中 "所有" 的抽象方法 //推荐使用
要么实现类定义为抽象类
5.多态的总结
1.接口多态 //最常用
2.抽象类多态 //常用
3.具体类多态 //基本不用
三、接口的成员特点
1.成员变量
*只能是常量
*默认修饰符:public static final
//建议手动给出默认的修饰符
2.构造方法
*接口没有构造方法
3.成员方法
*只能是抽象方法
*默认修饰符: public abstract
//建议手动给出默认的修饰符
四、猫狗案例接口版
//问题:抽象类和接口中都有抽象方法,那么我怎么知道哪些抽象方法需要放在抽象类中?哪些抽象方法需要放在接口中?
案例中出现的抽象方法有两个: 跳高:abstract void jump() 吃的方法:abstract void eat();
抽象类中: //抽象类的本质是替代继承中的父类,父类是所有子类都具有的方法 "共有功能"
abstract void eat()
接口中: 特有/额外的功能
abstract void jump()
举例:英雄联盟
抽象方法 :Q W E R ------------- 是所有的英雄都共有的,所以放在抽象类中
抽象方法: 真实伤害 ------------ 是部分英雄特有的,所以放在接口中
//定义抽象类
abstract class Hero{
void Q();
void W();
void E();
void R();
}
interface Hurt{
void kill();
}
class Gay伦 extends Hero implements Hurt{
void Q(){
System.out.println("Q技能");
}
void W(){
System.out.println("W技能");
}
void E(){
System.out.println("E技能");
}
void R(){
System.out.println("R技能");
}
void kill(){
System.out.println("真实伤害");
}
}
五、类和接口的关系
1.类和类的关系
继承关系,只能单继承、不能多继承,但是可以多层继承
*为什么不能多继承的原因
public class Father {
public void show(){
System.out.println("Fu");
}
}
-----------------------------------------
public class Mother {
public void show(){
System.out.println("Mo");
}
}
---------------------------------------------
public class Zi extends Father,Mother{
}
------------------------------------------------
public class Demo1 {
public static void main(String[] args) {
Zi zi = new Zi();
zi.show(); //在这里调用show方法,虚拟机不知道到底该调用Father类中的show方法还是该调用Mother中的show方法
}
}
2.类和接口的关系
实现关系,可以单实现,也可以多实现
3.接口和接口的关系
继承关系,可以单继承、也可以多继承
举例://为什么接口可以多继承
interface English{
void speak();
}
interface Chinese{
speak();
}
interface japanese extends English,Chinese{
speak(); //由于接口中的方法都是抽象方法,而抽象方法是没有方法体的,所有直接继承过来两个相同声明的抽象个方法,是不用区分的
}
六、抽象类和接口的区别
1.成员区别
抽象类:
*成员变量:
变量、常量、
*构造方法
有构造方法
*成员方法
普通方法、抽象方法
接口:
*成员变量:
常量(public static final)
*构造方法
没有构造方法
*成员方法
抽象方法(public abstract)
2.关系区别
类和类:继承关系,单继承
类和接口:实现关系,单实现、多实现
接口和接口:继承关系,单继承、多继承
3.设计理念区别
抽象类:完成的是一些共性功能的抽取 //所有子类共有功能
接口:完成的是一些特性功能的抽取 // 部分实现类特有功能