1 多态基础概念
1.1 多态理解
1.2 多态的使用场景
1.3 多态基础
1.4 练习
学生类:
属性:姓名,账号,密码
行为:work:学生的工作是学习
老师类:
属性:姓名,账号,密码
行为:work:老师的工作是教书
管理员:
属性:姓名,账号,密码
行为:work:管理员的工作是管理网站
学生管理系统:
行为:注册register
要求:能注册所有的角色
输出:姓名为张三的同学注册成功,账号zhangsan,密码123456
test1.Person
package com.itstudy.test1; public class Person { private String name;//姓名 private String account;//账号 private String password ;//密码 //无参构造方法 public Person() { } //有参构造方法 public Person(String name, String account, String password) { this.name = name; this.account = account; this.password = password; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAccount() { return account; } public void setAccount(String account) { this.account = account; // Changed from this.account = account; to this.account = account; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public void work(){ System.out.println("工作"); } }test1.Student
package com.itstudy.test1; public class Student extends Person { //构造方法 public Student() { } public Student(String name, String account, String password) { super(name, account, password); } //方法重写 @Override public void work() { System.out.println("学生的工作是学习"); } }test1.Teacher
package com.itstudy.test1; public class Teacher extends Person { //构造方法 public Teacher() { } public Teacher(String name, String account, String password) { super(name, account, password); } @Override public void work() { System.out.println("老师的工作是教书"); } }test1.Manager
package com.itstudy.test1; public class Manager extends Person { public Manager() { } public Manager(String name, String account, String password) { super(name, account, password); } @Override public void work() { System.out.println("管理员的工作是管理网站"); } }test1.StudentManger
package com.itstudy.test1; public class StudentManger { //定义一个方法表示注册用户 //参数Person:此时可以传递Person本身的对象,同时也可以传递Person所有的子类对象 public void register(Person person) { //输出:姓名为张三的同学注册成功,账号zhangsan,密码123456 System.out.println("姓名为" + person.getName() + "的账号注册成功,账号" + person.getAccount() + ",密码" + person.getPassword()); //传递不同的对象,调用不同类里面的work方法 person.work(); } }test1.Test
package com.itstudy.test1; public class Test { public static void main(String[] args) { /* 学生类: 属性:姓名,账号,密码 行为:work:学生的工作是学习 老师类: 属性:姓名,账号,密码 行为:work:老师的工作是教书 管理员: 属性:姓名,账号,密码 行为:work:管理员的工作是管理网站 学生管理系统: 行为:注册register 要求:能注册所有的角色 输出:姓名为张三的同学注册成功,账号zhangsan,密码123456 */ //创建学生管理系统的对象 StudentManger sm = new StudentManger(); //创建一个学生的对象 Student stu = new Student("张三", "zhangsan", "123456"); //把stu注册到学生管理系统当中 sm.register(stu); //创建一个老师的对象 Teacher tea = new Teacher("刘亚楠", "liuyanan", "123456"); sm.register(tea); } }1.5 小结
2 多态调用成员的特点
2.1 变量调用
调用成员变量: 编译看左边,运行也看左边
编译看左边:在把java文件编译成class文件的时候 ,看父类当中有没有这个变量,如果有编译成功,如果没有编译失败
运行看左边:在代码真正运行的时候,使用父类中的变量
2.2 方法调用
调用成员方法:编译看左边,运行看右边
编译看左边:看父类当中有没有这个方法,如果没有代码报错
运行看右边:在代码真正运行的时候,运行的是子类里面的方法,如果子类没有重写父类里面的方法,使用的还是父类
2.3 多态的弊端
多态的弊端:不能调用子类的特有方法
解决多态的弊端:把对象再转回子类类型的就可以了 例: Zi z = (Zi) f;
2.4 类型转换
转类型注意点:
// 爷爷 爸爸 儿子
//创建了爸爸的对象,赋值给了爷爷类型
//在进行强制类型转换的时候,只能转到爸爸类型,不能转成儿子类型
Ye y = new Fu();//创建了爸爸的对象,赋值给了爷爷类型
Fu f1 = (Fu)y;//正确
Zi z1 =(Zi)y; //报错 //创建了爸爸的对象,赋值给了爷爷类型
//在进行强制类型转换的时候,只能转到爸爸类型,不能转成儿子类型
解决方法:面对这种容易转错的情况,可以先对其进行判断
//判断一下,y是不是父亲类型的
if (y instanceof Fu) {
Fu f1 = (Fu) y;
f1.show();
} else {
System.out.println("请确定好类型再转换");
}
2.5 练习
Test2.Ye
package com.itstudy.Test2; public class Ye { String name="Ye"; public void fushow(){ System.out.println("ye类的fushow方法被调用啦!"); } public void show(){ System.out.println("ye的show方法被调用啦!"); } }Test2.Fu
package com.itstudy.Test2; public class Fu extends Ye{ String name="Fu"; public void fushow(){ System.out.println("父类的fushow方法被调用啦!"); } public void show(){ System.out.println("父类的show方法被调用啦!"); } }Test2.Zi
package com.itstudy.Test2; public class Zi extends Fu { String name="Zi"; //子类独有的方法 public void zishow(){ System.out.println("子类的zishow方法被调用啦!"); } //子类重写父类的方法 @Override public void show(){ System.out.println("子类重写的show方法被调用啦!"); } }Test2.Test
package com.itstudy.Test2; public class Test { public static void main(String[] args) { /* * 变量调用: * 编译看左边,运行也看左边 * 方法调用: * 编译看左边,运行看右边 */ //利用多态方式创建对象 Fu f = new Zi(); // 调用成员变量: 编译看左边,运行也看左边 // 编译看左边:在把java文件编译成class文件的时候 // 看父类当中有没有这个变量,如果有编译成功,如果没有编译失败 // 运行看左边:在代码真正运行的时候,使用父类中的变量 System.out.println(f.name); // System.out.println(f.age); //调用成员方法:编译看左边,运行看右边 // 编译看左边:看父类当中有没有这个方法,如果没有代码报错 // 运行看右边:在代码真正运行的时候,运行的是子类里面的方法 // 如果子类没有重写父类里面的方法,使用的还是父类 f.show(); //问题一:为什么调用fushow方法程序没有报错? // 因为fushow方法在父类当中存在,编译不会报错(遵循编译看左边的原则) //问题二:程序运行的结果是什么? // 程序运行的结果是:父类的fushow方法被调用啦!(子类没有这个方法,使用的还是父类的) f.fushow(); // f.zishow(); 报错,因为zishow方法在子类当中不存在,编译会报错(遵循编译看左边的原则) //多态的弊端:不能调用子类的特有方法 //解决多态的弊端: // 把对象再转回子类类型的就可以了 Zi z = (Zi) f; z.zishow(); //注意点: // 爷爷 爸爸 儿子 //创建了爸爸的对象,赋值给了爷爷类型 //在进行强制类型转换的时候,只能转到爸爸类型,不能转成儿子类型 Ye y = new Fu(); /* Fu f1 = (Fu)y; //创建了爸爸的对象,赋值给了爷爷类型 Zi z1 =(Zi)y; //报错 //创建了爸爸的对象,赋值给了爷爷类型 //在进行强制类型转换的时候,只能转到爸爸类型,不能转成儿子类型 */ //面对这种容易转错的情况,可以先对其进行判断 //判断一下,y是不是父亲类型的 if (y instanceof Fu) { Fu f1 = (Fu) y; f1.show(); } else { System.out.println("请确定好类型再转换"); } } }输出结果:
Fu
子类重写的show方法被调用啦!
父类的fushow方法被调用啦!
子类的zishow方法被调用啦!
父类的show方法被调用啦!
2.6 小结
3 多态的综合练习
test3.Person
package com.itstudy.test3; public class Person { private String name; private int age;//年龄 private String gender;//性别 public Person() { } public Person(String name, int age, String gender) { this.name = name; this.age = age; this.gender = gender; } 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 String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public void useTransport(Transport transport){ transport.move(); // transport.honk();//多态中不能直接调用子类特有方法 if(transport instanceof Car){ Car c = (Car)transport; c.honk(); } else if(transport instanceof Bicycle){ Bicycle bic = (Bicycle)transport; bic.ringBell(); }else{ System.out.println("没有这个类型"); } } }test3.Transport
package com.itstudy.test3; public class Transport { private String brand; private double speed; public Transport() { } public Transport(String brand, double speed) { this.brand = brand; this.speed = speed; } public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public double getSpeed() { return speed; } public void setSpeed(double speed) { this.speed = speed; } public void move() { System.out.println(brand+"的交通工具正在以"+speed+"的速度移动"); } }test3.Bicycle
package com.itstudy.test3; public class Bicycle extends Transport { public Bicycle() { } public Bicycle(String brand, double speed) { super(brand, speed); } @Override public void move() { System.out.println(getBrand()+"的交通工具正在以"+getSpeed()+"的速度移动"); } public void ringBell() { System.out.println("自行车正在响铃"); } }test3.Car
package com.itstudy.test3; public class Car extends Transport { public Car() { } public Car(String brand, double speed) { super(brand, speed); } @Override public void move() { System.out.println(getBrand()+"的交通工具正在以"+getSpeed()+"的速度移动"); } public void honk() { System.out.println("汽车正在鸣笛"); } }test3.Test
package com.itstudy.test3; public class Test { public static void main(String[] args) { /* 练习 多态的综合练习 自行车:Bicycle 属性:品牌,行驶速度 行为:移动 move,响铃 ringBell() 汽车:Car 属性:品牌,行驶速度 行为:移动 move,鸣笛 honk() 人:Person 属性:名字,年龄,性别 行为:行驶交通工具(能使用所有交通工具) 交通工具 Transport */ Person per = new Person("张三", 18, "男"); //ai没有自动生成代码时:Alt+P 强制ai生成代码 或者 写注释,提示ai生成 //输出打印对象的所有信息 System.out.println(per.getName() + " " + per.getAge() + " " + per.getGender()); Bicycle bic = new Bicycle("凤凰牌自行车", 25); per.useTransport(bic); Car c = new Car("玛莎拉蒂汽车", 60); per.useTransport(c); } }输出结果:
张三 18 男
凤凰牌自行车的交通工具正在以25.0的速度移动
自行车正在响铃
玛莎拉蒂汽车的交通工具正在以60.0的速度移动
汽车正在鸣笛