- 多态(重点)
生活中的多态:客观事物在人脑中的主观反应;也就是说对象与某个类间存在“is a”关系
例如:大黄是一条狗,也是一个动物,这种关系就是多态的形成
程序中的多态:父类引用指向子类对象,在程序中形成了多态
用法: 可以调用父类的方法,但是不能调用子类独有的方法
多态核心
//案例:大黄是一条狗,也是一个动物
//分析: 类: 狗类 动物类 对象: 大黄 方法: 动物类-吃 狗类-跑
class Animal{
public void eat() {
System.out.println("动物正在吃...");
}
}
class Dog extends Animal{
public void run() {
System.out.println("大黄正在跑...");
}
}
public class Test1 {
public static void main(String[] args) {
/*
Dog dog = new Dog(); //把狗当成狗类看待-->可以调子类自身方法,也可以根据继承调父类方法
dog.run();
dog.eat();
*/
Animal animal = new Dog(); //多态的核心-->把狗当成动物来看待,可以调动物类的方法,但狗类独有方法不能调用
animal.eat();
//animal.run(); //不能调子类独有方法
}
}
多态直接引用
//案例:大黄是一条狗,也是一个动物
//分析: 类: 狗类 动物类 对象: 大黄 方法: 动物类-吃 狗类-跑
//升级:狗类重写父类的方法,应该如何调用?
//多态的应用: 父类引用指向子类对象,优先调用子类重写的方法
//方式1:子类对象直接赋值给父类
class Animal2{
public void eat() {
System.out.println("动物正在吃...");
}
}
class Dog2 extends Animal2{
public void run() {
System.out.println("大黄正在跑...");
}
@Override
public void eat() {
System.out.println("大黄正在吃...");
}
}
public class Test2 {
public static void main(String[] args) {
Animal2 animal2 = new Dog2();
animal2.eat(); //父类引用指向子类对象,优先调用子类重写的方法
}
}
多态以传参方式出现
案例: 老师开着法拉利牌自行车去上班
分析:
类: 老师类 自行车类
对象: new new
属性: 姓名 品牌
方法: 开 运转
升级: 老师法拉利牌开汽车…
问题:当我们扩展了开地铁类,飞机类,大炮,那么在Teacher类中需要增加很多开的方法(冗余太多,麻烦,可维护性不强)
改造: 自行车,汽车,地铁,飞机等都是交通工具,都具备运转功能
多态的好处: 使得程序的扩展性,可维护性更强
class JiaoTongTool{
public void run() {
System.out.println("交通工具在运转...");
}
}
class Bike extends JiaoTongTool{
@Override
public void run() {
System.out.println("自行车运转: 轮子转啊转,以每小时50公里速度~");
}
}
class Car extends JiaoTongTool{
@Override
public void run() {
System.out.println("汽车运转:以每小时100公里速度前进~");
}
}
class Teacher{
//重写 VS 重载
//重载: 在同一个类中,方法名相同,参数个数或类型不同
//重写:在继承关系中,子类返回值,方法名,参数类型和父类完全一致,且子类权限大于等于父类
//-----------重载方法----------
/*
public void start(Bike bike) {//Bike bike = new Bike();
bike.run(); //自行车的运转
}
public void start(Car car) {
car.run(); //自行车的运转
}*/
//面向对象的设计原则:ocp原则,开闭原则
//o-open: 对外新增的代码持开放状态-扩展性 (升级新增飞机类,大炮等)
//c:close:对内修改的代码持关闭状态-灵活性,可维护性 (Teacher类的start方法不要变更,只需用交通工具类接收)
//以传参形式实现多态:
//应用:父类引用指向子类对象,可调用子类重写方法
public void start(JiaoTongTool tool) {
tool.run(); //不要看谁调的,要看谁传的
}
}
public class Test {
public static void main(String[] args) {
Teacher teacher = new Teacher();
teacher.start(new Bike()); //1.老师开自行车
teacher.start(new Car()); //2.老师开汽车
//new Bike().run(); //等价Teacher的start方法里面bike对象的调用
}
}
传参方式实现多态案例2
//案例:主人喂养动物,狗是动物,猫是动物,以传参形式实现多态
//抽取: 父类引用指向子类对象,调子类重写方法--->狗,猫是动物,具备吃的行为
//类: 主人类 动物类 狗类 猫类
//行为: 主人类: 喂养 动物类:吃 狗,猫: 重写吃
//案例1:金鱼,乌龟都是水生动物,具备吃的行为
//案例2:面条,面包都是食物,都具备提高营养能力
//案例3:王者,吃鸡都是游戏,都具备充值能力
class Animal{
public void eat() {
System.out.println("动物在吃...");
}
}
class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗在吃...");
}
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫在吃...");
}
}
class Master{
public void feed(Animal animal) {
//多态
animal.eat(); //谁传给我,就是谁在吃
}
}
public class Test2 {
public static void main(String[] args) {
Master master = new Master();
master.feed(new Dog()); //主人喂狗,狗在吃
master.feed(new Cat()); //主人喂猫,猫在吃
}
}
多态以返回值形式出现
//案例:主人购买动物,选择购买编号:1.买狗 2.买鸟
//分析:
//类: 主人类 动物类 狗类 鸟类
//行为:购买 叫
class Animal{
public void bark() {
System.out.println("动物在叫..");
}
}
class Dog extends Animal{
@Override
public void bark() {
System.out.println("狗在叫..");
}
}
class Bird extends Animal{
@Override
public void bark() {
System.out.println("鸟在叫...");
}
}
class Master{
public Animal buy(int num) {
switch (num) {
case 1:
return new Dog(); //多态以返回值方式出现
case 2:
return new Bird();
default:
return null;
}
}
}
public class Test {
public static void main(String[] args) {
System.out.println("请输入你要购买的宠物: 1.狗 2.鸟");
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
Master master = new Master();
//多态以返回值方式出现
Animal animal = master.buy(num); //Animal a = new Dog();
if(animal!=null) {
animal.bark(); //调重写方法
}else {
System.out.println("没有这个购买的宠物");
}
}
}
导入源码包:
- 抽象类(重点)
生活中的抽象:从网上搜索动物类,可以具体化子类对象;但是不能具体化动物的对象
程序中的抽象类:有一个类不能够具体化出来对象,这个类就是抽象类
程序中的抽象方法:往往在抽象类中,有这个方法但不能具体实现,这个方法叫做抽象方法
例如: 动物类不能具体化,这个动物类就是抽象类;
动物类一般都有叫的方法,但不能具体实现,叫的方法我们可以设置为抽象方法;
抽象方法用处:作为一个模板,该抽象类的子类必须完成抽象方法的重写
案例: 动物类都有叫的方法,狗类,猫类(子类)完成具体实现
抽取多态: 狗,猫是动物,具备叫的行为
抽象类概述
//抽象类: 限制该类不能被具体化
//抽象类的好处:1.作为模板使用, 2.更自然的使用多态
//抽象类的特点整理:
//1.抽象类能否实例化对象? 不能
//2.能否有构造方法? 可以有
//3.抽象类中能否有非抽象方法? 可以有
//4.抽象类中能否没有抽象方法? 可以,但一般都要写抽象方法
//5.父类是抽象类,子类必须重写父类方法吗? 不是必须的,可以把自身变为抽象类
//6.有抽象方法的类必须是抽象类吗? 是的
abstract class Animal{
public Animal() {
} //可以有构造方法,交给子类调用
public void eat(){
} //有非抽象方法
//抽象类中的一些方法,往往有这个方法,但没法实现,这样的方法设置为抽象方法
//抽象方法作为模板
public abstract void bark();
}
//The type Dog must implement the inherited abstract method Animal.bark()
//父类为抽象类,子类有两种处理方案
//1.子类要重写父类的方法
//2.将子类也变为抽象类,交给Dog子类去完成
class Dog extends Animal{
@Override
public void bark() {
System.out.println("狗正在旺旺旺地叫...");
}
public void run() {
System.out.println("狗正在跑...");
}
}
abstract class Cat extends Animal{
}
public class Test1 {
public static void main(String[] args) {
//Animal animal = new Animal(); //不合适
//抽象类实现多态: 抽象类指向子类对象,即可调用子类重写方法
//Dog dog = new Dog(); //?
Animal animal = new Dog(); //多态,扩展性,维护性更强
animal.bark();
//animal.run(); //不能调子类独有方法(当次动物看待,只能调动物的方法或子类重写的)
}
}
抽象类案例
/*
案例: 老师开着法拉利牌自行车去上班
改造: 自行车,汽车,地铁,飞机等都是交通工具,都具备运转功能
将交通工具类变为抽象类,通过抽象类实现多态
分析: 交通工具类不能具体化---抽象类
交通工具的运行功能---有这个功能,但不知道如何实现,抽象方法
* */
abstract class JiaoTongTool{
public abstract void run();
}
class Bike extends JiaoTongTool{
@Override
public void run() {
System.out.println("自行车运转: 轮子转啊转,以每小时50公里速度~");
}
}
class Car extends JiaoTongTool{
@Override
public void run() {
System.out.println("汽车运转:以每小时100公里速度前进~");
}
}
class Teacher{
//以传参形式通过抽象类实现多态:
public void start(JiaoTongTool tool) {
tool.run(); //不要看谁调的,要看谁传的
}
}
public class Test2 {
public static void main(String[] args) {
//抽象类实现多态
Teacher teacher = new Teacher();
teacher.start(new Bike()); //1.老师开自行车
teacher.start(new Car()); //2.老师开汽车
}
}