方法的多态
方法的多态案例:
对象的多态
父类的引用可以指向子类的对象,所以说编译类型和运行类型可以不一致,案例中animal就为编译类型,Dog为运行类型。
package com.Polymorphic_test01;
public class Play {
public static void main(String[] args) {
Master tom = new Master("Tom");
Dog dog = new Dog("小黄");
Food food = new Food("骨头");
tom.Feed(dog,food);
}
}
public class Animal {
String name;
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Cat extends Animal{
public Cat(String name) {
super(name);
}
}
public class Dog extends Animal{
public Dog(String name) {
super(name);
}
}
public class Pig extends Animal{
public Pig(String name) {
super(name);
}
}
public class Food {
String name;
public Food(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Fish extends Food{
public Fish(String name) {
super(name);
}
}
public class Rice extends Food{
public Rice(String name) {
super(name);
}
}
public class Bone extends Food{
public Bone(String name) {
super(name);
}
}
public class Master {
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());
// }
// public void feed(Cat cat,Fish fish)
// {
// System.out.println(name+"给"+cat.getName()+"喂"+fish.getName());
// }
//.........创建了哪个就要写一个相应对象的方法非常麻烦因此可以使用多态的知识点来写。
//Animal和Food为编译类型,可以引用相应的子类对象。
// cat,dog都是animal的子类对象,所以直接用animal类型来接收,fish和bone为food的子类
public void Feed( Animal animal,Food food)
{
System.out.println(name+"给"+animal.getName()+"喂"+food.getName());
}
}
向下转型
子类
、
父类animal无法调用子类的成员(对象和方法)。
向上转型的调用方法:
由图可见,animal的运行类型为cat则anim.eat();时,先看cat类中有无eat()方法如果没有则在去cat父类查找有无eat()方法,父类没有则去父类的父类。。。。直到找到为止
向下转型
图一:
图二:
图三:
解析:
在最开始的定义时,animal已经指向了cat(见图一),满足向下转型第三点,所以后续可以将animal强制转换为cat类型(见图二),但是并未将animal指向dog,所以在强制转换成dog出错(见图三)
instanceOf
列题
动态绑定机制
package com.Polymorphic_dynamic_binding_test01;
public class dynamic_binding {
public static void main(String[] args) {
A a=new B();
a.sum1();//15
a.sum();//20
}
}
class A{
int i=10;
public void sum()
{//直接用i费调用方法则不会发生动态绑定
System.out.println(i+10);
}
public void sum1()
{
//sum1中i的值是用一个方法获取的getI(),且a向下转型了
//调用方法时,属性会跟运行类型进行动态绑定
//所依此时的getI()为运行类型的(B类中)
//如果运行类型没有getI()方法,就会去他的父类找。。。。直到找到为止
System.out.println(getI()+10);
}
public int getI() {
System.out.println("1111");
return i;
}
}
class B extends A{
int i=5;
// public void sum()
// {
// System.out.println(i+10);
// }
// public void sum1()
// {
// System.out.println(getI()+10);
// }
public int getI() {
//System.out.println("2222");
return i;
}
}
多态数组
package com.Polymorphic_Arr;
package com.Polymorphic_Arr;
public class Infromation {
public static void main(String[] args) {
Person person[]=new Person [3];
person[0] =new Person("jack", 18);
person[1]=new Student("小美",16,12345,99.5);
person[2]=new Teacher("呼呼",20,200000,"数学");
for(int i=0;i<person.length;i++)
{
//编译类型都是Person但是运行类型根据数组下标对应的改变,
// 如果下标是0则是运行;类型为Person,为2则为Teacher
//调用方法say时,say中值也是采用的调用方法,此时便会实现动态绑定
person[i].say();
//当我们想要调用子类特有的方法时,我们可以使用强转类型来达成目的
//我们可以先判断当前的运行类型是否为编译类型的子类,如果是则开始强转类型
if (person[i]instanceof Student)
{
//表达方式一
// ((Student)person[i]).study();
//((强转类型)当前类型的变量名).强转后类型中所需的方法已强转后的这个整体来调用该类型中的方法
Student student=(Student) person[i];
//方式二
student.study();
}
else if (person[i]instanceof Teacher)
{
((Teacher) person[i]).teach();
}
else
continue;
}
}
}
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 void say()
{
System.out.println(getName()+" "+getAge());
}
}
public class Student extends Person {
int id;
double score;
public Student(String name, int age, int id, double score) {
super(name, age);
this.id = id;
this.score = score;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public void say()
{
System.out.println(getName()+" "+getAge()+" "+getId()+" "+getScore());
}
public void study()
{
System.out.println("开始上课啦!");
}
}
public class Teacher extends Person{
double salary;
String count;
public Teacher(String name, int age, double salary, String count) {
super(name, age);
this.salary = salary;
this.count = count;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getCount() {
return count;
}
public void setCount(String count) {
this.count = count;
}
public void say()
{
System.out.println(getName()+" "+getAge()+" "+getSalary()+" "+getCount());
}
public void study()
{
System.out.println("老师开课啦!");
}
}
输出结果:
多态参数
package com.Polymorphic_attribute;
public class Main {
public static void main(String[] args) {
CommonEmplopee xiao = new CommonEmplopee("xiao", 20000);
ManageEmployee tingting = new ManageEmployee("tingting", 67881, 234567);
Main main = new Main();//在该类写了showEmpAnnal()和testWork()方法则需要创建该类来使用方法
main.showEmpAnnal(xiao);
main.showEmpAnnal(tingting);
main.testWork(xiao);
main.testWork(tingting);
}
public void showEmpAnnal(Employee e) {
System.out.println(e.getAnnual());
}
public void testWork(Employee e) {
if (e instanceof CommonEmplopee)
((CommonEmplopee) e).work();
else if (e instanceof ManageEmployee)
((ManageEmployee) e).manage();
else
System.out.println("出错");
}
}
package com.Polymorphic_attribute;
/*经理类多了奖金bonus属性和管理manage方
法,普通员工和经理类要求分别重写getAnnual方法
*/
public class ManageEmployee extends Employee{
double bonus;
public ManageEmployee(String name, double annual, double bonus) {
super(name, annual);
this.bonus = bonus;
}
public double getAnnual()
{
return super.getAnnual()+bonus;//管理员工与父类年薪计算不同,多个奖金,则调用父类的年薪计算方法再加奖金
}
public void manage()
{
System.out.println(name+"正在管理");
}
}
package com.Polymorphic_attribute;
/*
* 普通员工和经理继承了员工,普通员工类多了work方法,*/
public class CommonEmplopee extends Employee{
public CommonEmplopee(String name, double salary) {
super(name, salary);
}
public double getAnnual()
{
return super.getAnnual() ;//普通员工无奖金所以年薪计算方式与父类相同,直接使用super调用父类的方法
}
public void work()
{
System.out.println(name+"正在努力工作");
}
}