含义:方法或对象具有多种形态,是面向对象的第三大特征,多态建立在封装和继承的基础之上的;
业务场景:请编写一个程序,master类中有一个feed(喂食方法),可以完成主任给动物喂食物的信息;
思路分析
/*
1、创建父类 - 食物类Food
1.1、创建子类 - Fish继承Food;
1.2、创建子类 - Bone继承Food;
2、创建父类 - 动物类Animal
2.1、创建子类 - Dog继承Animal
2.2、创建子类 - Cat继承Animal
3、创建Master类 - feed方法
*/
//1、创建父类 - 动物类Animal
package com.taobao;
public class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//1.1、创建子类 - Dog继承Animal
package com.taobao;
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
}
//1.2、创建子类 - Cat继承Animal
package com.taobao;
public class Cat extends Animal{
public Cat(String name) {
super(name);
}
}
//2、创建父类 - 食物类Food
package com.taobao;
public class Food {
//1、食物名称属性定义
private String name;
//2、构造器
public Food(String name) {
this.name = name;
}
//3、生成一个get/set方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//2.1、创建子类 - Fish继承Food;
package com.taobao;
public class Fish extends Food {
public Fish(String name) {
super(name);
}
}
//2.2、创建子类 - Bone继承Food;
package com.taobao;
public class Bone extends Food {
public Bone(String name) {
super(name);
}
}
//3、创建Master类
package com.taobao;
public class Master {
private String name;
public Master(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//1、主人给小狗喂食骨头
public void feed(Dog dog,Bone bone){
System.out.println("主人" + name + "给" + dog.getName() + "吃" + bone.getName());
}
//2、主人给小狗喂食骨头
public void feed(Cat cat,Fish fish){
System.out.println("主人" + name + "给" + cat.getName() + "吃" + fish.getName());
}
}
//4、创建main方法调用上述类
package com.taobao;
public class hello {
public static void main(String[] args) {
//1、主人汤姆给大黄吃大棒骨
Master tom = new Master("汤姆");
Dog dog = new Dog("大黄");
Bone bone = new Bone("大棒骨");
tom.feed(dog,bone);
//2、主人汤姆给小花猫吃黄花鱼
Cat cat = new Cat("小花猫");
Fish fish = new Fish("黄花鱼");
tom.feed(cat,fish);
}
}
①编译期间决定目标方法
②通过overloading重载实现
③方法名相同,参数不同
public int sum(int n1,int n2){
return n1 + n2;
}
public int sum(int n1,int n2,int n3){
return n1 + n2 + n3;
}
①一个对象的编译类型和运行类型可以不一致;
②编译类型在定义对象时,就确定了,不能改变;
③运行类型是可以变化的;
④编译类型看定义时 = 号的左边,运行类型看 = 号的右边;
// 可以让父类的引用指向子类的对象
Animal animal = new Dog()
// animal的编译类型是Animal,运行类型是Dog
animal = new Cat()
// animal的编译类型仍然是Animal,运行类型变成了Cat
①编译时多态内存剖析
后续更新
②运行时多态内存剖析
后续更新
①成员变量:使用的是父类的
②成员方法:由于存在重写现象,使用的是子类的
③静态成员:随着类的加载而加载,谁调用返回谁
package com.taobao;
public class hello {
public static void main(String[] args) {
// 重载体现多态:传入不同方法,会调用不同sum方法,体现多态
B b = new B();
System.out.println("两个参数的和:"+b.sum(1,2));
System.out.println("三个参数的和:"+b.sum(1,2,3));
}
}
class A { // 父类
public void say(){
System.out.println("A say() 方法被调用...");
}
}
class B extends A{ // 子类
public int sum(int n1,int n2){
return n1 + n2;
}
public int sum(int n1,int n2,int n3){
return n1 + n2 + n3;
}
}
package com.taobao;
public class hello {
public static void main(String[] args) {
// 方法重写体现多态:因方法重写,会自动定位相应的方法
A a = new A();
B b = new B();
a.say();
b.say();
}
}
class A { // 父类
public void say(){
System.out.println("A say() 方法被调用...");
}
}
class B extends A{ // 子类
public void say(){
System.out.println("B say() 方法被调用...");
}
public int sum(int n1,int n2){
return n1 + n2;
}
public int sum(int n1,int n2,int n3){
return n1 + n2 + n3;
}
}
//1、定义父类 - Animal类
public class Animal {
public void cry(){
System.out.println("动物在叫");
}
}
//2、定义子类 - Dog类继承Animal
public class Dog extends Animal {
public void cry(){
System.out.println("小狗汪汪叫...");
}
}
//3、定义子类 - Cat继承Animal
public class Cat extends Animal {
public void cry(){
System.out.println("小猫喵喵叫...");
}
}
//4、main方法引用
public class poly2 {
public static void main(String[] args) {
//体验对象多态特点
//animal 编译类型为Animal , 运行类型 Dog
Animal animal = new Dog();
//因为运行时,这时就执行到该行时,animal运行类型是Dog,所以cry就是Dog的cry
animal.cry();
//animal 编译类型Animal,运行类型就是Cat,指针指向猫
animal = new Cat();
animal.cry();
}
}
多态前提:两个对象(类)存在继承关系;
范例:使用多态可以统一的管理主人喂食问题,简化feed方法
//1、使用多态机制
public class Mater {
private String name;
public Mater(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//多态:使用多态机制,可以统一的管理主人喂食的机制
//animal 编译类型是Animal,可以指向(接收)Animal子类的对象
//animal 编译类型是Food,可以指向(接收)Food子类的对象
public void feed(Animal animal,Food food){
System.out.println("主人" + name + "给" + animal.getName() + "吃" + food.getName());
}
}
//2、创建子类 - Pig继承Animal类
public class Pig extends Animal {
public Pig(String name) {
super(name);
}
}
//3、创建子类 - Rice继承Food类
public class Rice extends Food {
public Rice(String name) {
super(name);
}
}
//4、编写main方法
public class Poly01 {
public static void main(String[] args) {
//1、主人汤姆给大黄吃大棒骨
Mater tom = new Mater("汤姆");
Dog dog = new Dog("大黄");
Bone bone = new Bone("大棒骨");
tom.feed(dog,bone);
//2、主人汤姆给小花猫吃黄花鱼
Cat cat = new Cat("小花猫");
Fish fish = new Fish("黄花鱼");
tom.feed(cat,fish);
//3、主人汤姆给花花吃米饭
Pig pig = new Pig("花花");
Rice rice = new Rice("米饭");
tom.feed(pig,rice);
}
}
本质:父类的引用指向了子类的对象;
语法:父类类型 引用名 = new 子类类型() //把子类提上为父类
特点:编译类型看左边,运行类型看右边。
可以调用父类的所有成员(须遵守访问权限);
不能调用子类中的特有成员;
最终运行效果看子类的具体体现;
//1、创建父类Animal
public class Animal {
String name = "动物";
int age = 10;
public void sleep(){
System.out.println("睡觉!");
}
public void run(){
System.out.println("跑");
}
public void eat(){
System.out.println("吃");
}
public void show(){
System.out.println("hello world!");
}
}
//2、创建子类 - Cat继承Animal
public class Cat extends Animal {
public void eat(){ //方法重写
System.out.println("猫吃鱼");
}
public void catchMouse(){//cat特有方法
System.out.println("猫抓老鼠");
}
}
//3、编写main方法实现多态
public class poly {
public static void main(String[] args) {
//向上转型:父类的引用指向子类的对象
Animal animal = new Cat();
System.out.println("ok~~");
//注意事项:可以调用父类的所有成员(须遵守访问权限),但是不能调用子类特有的成员
// 因为在编译阶段能调用那些成员是由编译类型来决定的;
// 最终的运行效果看子类(运行类型)的具体实现,即调用方法,按照从子类开始查找方法然后调用,与继承规则一致
animal.eat();
animal.run();
animal.show();
animal.sleep();
}
}
使用场景:之前向上转型过的子类对象想要执行子类的特有功能,重新恢复成子类对象。
注意事项
范例
public class hello {
public static void main(String[] args) {
//向上转型:父类的引用指向子类的对象
Animal animal = new Cat();
//向下转型:cat的编译类型Cat,运行类型是Cat
Cat cat = (Cat) animal;
//Object animal1 = new Cat(); //可以定义,Object是animal的父类
System.out.println("ok~~");
animal.eat();
animal.run();
animal.show();
animal.sleep();
cat.catchMouse();
}
}
Java动态绑定机制
引入案例
package com.taobao;
public class hello {
public static void main(String[] args) {
A a = new B(); //向上转型
System.out.println(a.sum());
System.out.println(a.sum1());
}
}
class A {
public int i = 10;
public int sum(){
return get1() +10;
}
public int sum1(){
return i+10;
}
public int get1(){
return i;
}
}
class B extends A {
public int i = 20;
public int sum(){
return i + 20;
}
public int sum1(){
return i+10;
}
public int get1(){
return i;
}
}
package com.taobao;
public class hello {
public static void main(String[] args) {
A a = new B(); //向上转型
System.out.println(a.sum());
System.out.println(a.sum1());
}
}
class A {
public int i = 10;
public int sum(){
return get1() +10; //get1调用父类还是子类的,动态绑定机制,调用子类的get1
}
public int sum1(){
return i+10;
}
public int get1(){
return i+1;
}
}
class B extends A {
public int i = 20;
public int get1(){
return i;
}
}