多态
案例
编写一个程序,Master类中有一个feed(喂食)的方法,可以完成主人对动物喂食物的操作。
代码
food类
package com.xbxaq.poly_;
public class Food {
private String name;
public Food(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
fish类
package com.xbxaq.poly_;
public class Fish extends Food{
public Fish(String name){
super(name);
}
}
bone类
package com.xbxaq.poly_;
public class Bone extends Fish{
public Bone(String name){
super(name);
}
}
animal类
package com.xbxaq.poly_;
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;
}
}
dog类
package com.xbxaq.poly_;
public class Dog extends Animal{
public Dog(String name) {
super(name);
}
}
cat类
package com.xbxaq.poly_;
public class Cat extends Animal{
public Cat(String name) {
super(name);
}
}
master类
package com.xbxaq.poly_;
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;
}
// 完成主人对小狗的喂食效果
public void feed(Dog dog, Bone bone){
System.out.println("主人 " + name + " 给" + dog.getName() + "喂 " + bone.getName());
}
}
poly类
package com.xbxaq.poly_;
public class Poly01 {
public static void main(String[] args) {
Master tom = new Master("tom");
Dog dog = new Dog("小白");
Bone bone = new Bone("大白骨");
tom.feed(dog, bone);
}
}
运行结果
基本概述
- 方法或对象具有多种形态,是面向对象的第三大特征,多态是建立在封装和继承基础之上的。
多态的具体体现
1、方法的多态(重载与重写)
2、对象的多态
一个对象的编译类型和运行类型可以不一致。
编译类型在定义对象时,就确定了,不能改变
允许类型是可以变化的
编译类型看定义时 =号的左边,运行类型看 =号的右边
多态的细节
1、多态的前提是:两个对象(类)存在继承关系
2、多态的向上转型,本质为父类的引用指向了子类的对象
语法:父类类型 引用名 = new 子类类型()
特点:编译类型看右边,运行类型看左边
可以调用父类的所有成员(需遵守访问权限),不能调用子类的特有成员。
3、多态的向下转型
语法:子类类型 引用名 = (子类类型) 父类引用;
只能强转父类的引用,不能强转父类的对象
要求父类的引用必须指向的是当前目标类型的对象
当向下转型后可以调用子类类型中所有的成员
4、属性没有重写之说,属性的值看编译类型
animal类
cat类
Detail类
结果
动态绑定机制
- 当调用对象方法时,该方法会和对象的内存地址[也就是运行类型]进行绑定
- 当调用对象属性时,没有动态绑定机制,哪里声明哪里使用
示例代码-1
public class BangDing{
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 getl() + 10;
}
public int sum1(){
return i + 10;
}
public int getl(){
return i;
}
}
class B extends A {
public int i = 20;
public int sum(){
return i + 20;
}
public int getl(){
return i;
}
public int sum1(){
return i + 10;
}
}
代码示例-2
public class BangDing{
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 getl() + 10;
}
public int sum1(){
return i + 10;
}
public int getl(){
return i;
}
}
class B extends A {
public int i = 20;
// public int sum(){
// return i + 20;
// }
public int getl(){
return i;
}
public int sum1(){
return i + 10;
}
}
代码示例-3
public class BangDing{
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 getl() + 10;
}
public int sum1(){
return i + 10;
}
public int getl(){
return i;
}
}
class B extends A {
public int i = 20;
// public int sum(){
// return i + 20;
// }
public int getl(){
return i;
}
// public int sum1(){
// return i + 10;
// }
}
多态数组
- 多态数组:数组的定义类型为父类类型,里面保存的实际元素类型为子类类型
应用实例-1
现有一继承结构,要求创建一个person对象、两个student对象和两个teacher对象,统一放在数组中,并调用每个对象的say方法。
plaoarray类
public class PloyArray{
public static void main(String[] args){
Person[] person = new Person[5];
person[0] = new Person("zhangsan",30);
person[1] = new Student("wangwu",18,74.0);
person[2] = new Student("wangpeng",17,89.5);
person[3] = new Teacher("zhangxiwang",32,15000);
person[4] = new Teacher("luoping",32,20000);
//遍历多态数组调用say方法
for (int i = 0; i < person.length; i++) {
System.out.println(person[i].say()); //动态绑定机制
}
}
}
person类
public class Person{
private String name;
private int age;
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 String say(){
return name + "\t" + age;
}
}
teacher类
public class Teacher extends Person{
private double salary;
public Teacher(String name, int age,double salary){
super(name,age);
this.salary = salary;
}
public double getSalary(){
return salary;
}
public void setSalary(){
this.salary = salary;
}
@Override
public String say() {
return super.say() + " salary=" + salary;
}
}
student类
public class Student extends Person{
private double score;
public Student(String name, int age, double score){
super(name,age);
this.score = score;
}
public double getScore(){
return score;
}
public void setScore(double score){
this.score = score;
}
//重写say方法
public String say(){
return super.say() + " score=" + score;
}
}
运行效果
应用实例-2
如何调用子类特有的方法,例如:teacher类有一个teach方法,student类有一个study方法,该如何调用呢
plaoarray类
public class PloyArray{
public static void main(String[] args){
Person[] person = new Person[5];
person[0] = new Person("zhangsan",30);
person[1] = new Student("wangwu",18,74.0);
person[2] = new Student("wangpeng",17,89.5);
person[3] = new Teacher("zhangxiwang",32,15000);
person[4] = new Teacher("luoping",32,20000);
//遍历多态数组调用say方法
for (int i = 0; i < person.length; i++) {
System.out.println(person[i].say()); //动态绑定机制
if (person[i] instanceof Teacher){
((Teacher)person[i]).teach();
}
if (person[i] instanceof Student){
((Student)person[i]).study();
}
}
}
}
person类
public class Person{
private String name;
private int age;
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 String say(){
return name + "\t" + age;
}
}
teacher类
public class Teacher extends Person{
private double salary;
public Teacher(String name, int age,double salary){
super(name,age);
this.salary = salary;
}
public double getSalary(){
return salary;
}
public void setSalary(){
this.salary = salary;
}
@Override
public String say() {
return super.say() + " salary=" + salary;
}
public void teach(){
System.out.println("教师:" + getName());
}
}
student类
public class Student extends Person{
private double score;
public Student(String name, int age, double score){
super(name,age);
this.score = score;
}
public double getScore(){
return score;
}
public void setScore(double score){
this.score = score;
}
//重写say方法
public String say(){
return super.say() + " score=" + score;
}
public void study(){
System.out.println("学生" + getName());
}
}
运行效果
多态参数
- 多态参数:方法定的形参类型为父类类型,实参类型允许为子类类型
实例
需求:定义员工类Employee其中包含姓名name、月工资[private]以及计算年工资的getAnnual方法,普通员工和经理继承了员工,经理类多了奖金bonus属性和管理manage方法,普通员工类多了work方法,普通员工和经理类要求分别重写getAnnual方法
测试类中添加一个方法showEmpAnnual(employee e),实现获取任何员工对象的工资,并在main方法中调用该对象
测试类中添加一个方法testWork,如果是普通员工,则调用Work方法,如果是经理则调用manage方法
Employee类
public class Employee{
private String name;
private Double salary;
// 年工资
public double getAnnual(){
return 12 * salary;
}
public Employee(String name, Double salary){
this.name = name;
this.salary = salary;
}
public String getName(){
return name;
}
public Double getSalary(){
return salary;
}
public void setName(String name){
this.name = name;
}
public void setSalary(Double salary){
this.salary = salary;
}
}
worker类
public class Worker extends Employee{
public Worker(String name,double salary){
super(name,salary);
}
public void work(){
System.out.println("员工" + getName() + "正在工作");
}
public double getAnnual(){
return super.getAnnual();
}
}
manager类
public class Manager extends Employee{
private double bonus;
public void manage(){
System.out.println("经理" + getName() + "正在管理");
}
public Manager(String name,double salary,double bonus){
super(name,salary);
this.bonus = bonus;
}
public double getBonus(){
return bonus;
}
public void setBonus(double bonus){
this.bonus = bonus;
}
public double getAnnual(){
return super.getAnnual() + bonus;
}
}
PloyParameter类
public class PloyParameter{
public static void main(String[] args){
Worker tom = new Worker("tom",10.0);
Manager zhangsan = new Manager("zhangsan",7000,10000);
PloyParameter ployParameter = new PloyParameter();
ployParameter.showEmpAnnual(tom);
ployParameter.showEmpAnnual(zhangsan);
ployParameter.testWork(tom);
ployParameter.testWork(zhangsan);
}
//添加一个方法showEmpAnnual(employee)
public void showEmpAnnual(Employee e){
System.out.println(e.getAnnual());
}
// 添加一个方法testWork,如果是普通员工,则调用testWork方法,如果是经理则调用manage方法
public void testWork(Employee e){
if (e instanceof Worker){
((Worker) e).work();
}else if(e instanceof Manager){
((Manager) e).manage();
}
}
}
运行效果
细节讨论
属性看编译类型,方法看运行类型
属性没有重写之说,属性的值看编译类型
代码
public class a1{
public static void main(String[] args){
Base base = new Sub();
System.out.println(base.count);
Sub sub = new Sub();
System.out.println(sub.count);
}
}
class Base{
int count = 10;
}
class Sub extends Base{
int count = 20;
}
instanceOf比较操作符,用于判断对象的运行类型是否为xx类型或者xx类型的子类型
public class a1{
public static void main(String[] args){
Sub sub = new Sub();
System.out.println(sub instanceof Sub);
System.out.println(sub instanceof Base);
}
}
class Base{
}
class Sub extends Base{
}
本文系作者 @小白学安全 原创发布在 xbxaq.com 站点,未经许可,禁止转载!
评论