案例
编写一个程序,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;
// }
}
细节讨论
属性看编译类型,方法看运行类型
属性没有重写之说,属性的值看编译类型
代码
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{
}