• 动手动脑-多态


    怎样判断对象是否可以转换? 

    可以使用instanceof运算符判断一个对象是否可以转换为指定的类型:
    Object obj="Hello";
    if(obj instanceof String)
    System.out.println("obj对象可以被转换为字符串");

    下列语句哪一个将引起编译错误?为什么?哪一个会引起运行时错误?为什么?
      m=d;
      d=m;
      d=(Dog)m;
      d=c;(子类是否能给子类赋值)
      c=(Cat)m;

    源代码:

    class Mammal{}

    class Dog extends Mammal {}

    class Cat extends Mammal{}

    public class TestCast

    {

    public static void main(String args[])

    {

    Mammal m;

    Dog d=new Dog();

    Cat c=new Cat();

    m=d;//子类d可以给父类m赋值

    //d=m;

    d=(Dog)m;

    //d=c;//false

    //c=(Cat)m;

    }

     原因:子类对象可以直接赋给基类变量。

              基类对象要赋给子类对象变量,必须执行类型转换,其语法是:子类对象变量=(子类名)基类对象名。

    更改后的代码为:

    class Mammal{}

    class Dog extends Mammal {}

    class Cat extends Mammal{}

    public class TestCast

    {

    public static void main(String args[])

    {

    Mammal m;

    Dog d=new Dog();

    Cat c=new Cat();

    m=d;//子类d可以给父类m赋值

            d=m;

    d=(Dog)m;

    //d=c;//false 子类不可以给子类赋值

    c=(Cat)m;

    }

    }

    多态的含义和用途

    让我们看一个开发场景:

    某动物园有一饲养员小李,

    每天需要给他所负责饲养的狮子、猴子和鸽子喂食。

    请用一个程序来模拟他喂食的过程。

    三种动物对应三个类,每个类定义一个eat()方法,表示吃饲养员给它们的食物。

    再设计一个Feeder类代表饲养员,其name字段保存饲养员名字,三个方法分别代表喂养三种不同的动物,其参数分别引用三种动物

    public class Zoo

    {

    public static void main(String args[])
    {
    Feeder f = new Feeder("小李");
    // 饲养员小李喂养一只狮子
    f.feedLion(new Lion());
    // 饲养员小李喂养十只猴子
    for (int i = 0; i < 10; i++)
    {
    f.feedMonkey(new Monkey());
    }
    // 饲养员小李喂养5只鸽子
    for (int i = 0; i < 5; i++)
    {
    f.feedPigeon(new Pigeon());
    }
    }
    }
    class Feeder
    {
    public String name;
    public Feeder(String name)
    {
    this.name = name;
    }
    public void feedLion(Lion l)
    {
    l.eat();
    }
    public void feedPigeon(Pigeon p)
    {
    p.eat();
    }
    public void feedMonkey(Monkey m)
    {
    m.eat();
    }
    }
    class Lion
    {
    public void eat()
    {
    System.out.println("我不吃肉谁敢吃肉!");
    }
    }
    class Monkey
    {
    public void eat()
    {
    System.out.println("我什么都吃,尤其喜欢香蕉。");
    }
    }
    class Pigeon
    {
    public void eat()
    {
    System.out.println("我要减肥,所以每天只吃一点大米。");
    }
    }
    这种编程方式有什么不合理的地方?

    每次喂食都要创建一次类。重复步骤多。

     引入继承

    定义一个抽象基类Animal,其中定义一个抽象方法eat(),三个子类实现这个抽象方法。

    Feeder类的三个喂养方法现在可以合并为一个feedAnimal()方法,注意它接收一个类型为Animal参数,而不是三个具体的动物类型。

    依据多态特性,此方法将可以接收任何一个派生自Animal类的子类对象

    public class Zoo
    {
    public static void main(String args[])
    {
    Feeder f = new Feeder("小李");
    //饲养员小李喂养一只狮子
    f.feedAnimal(new Lion());
    //饲养员小李喂养十只猴子
    for (int i = 0; i < 10; i++)
    {
    f.feedAnimal(new Monkey());
    }
    //饲养员小李喂养5只鸽子
    for (int i = 0; i < 5; i++)
    {
    f.feedAnimal(new Pigeon());
    }
    }
    }
    class Feeder
    {
    public String name;
    Feeder(String name)
    {
    this.name = name;
    }
    public void feedAnimal(Animal an)
    {
    an.eat();
    }
    }
    abstract class Animal
    {
    public abstract void eat();
    }
    class Lion extends Animal
    {
    public void eat()
    {
    System.out.println("我不吃肉谁敢吃肉!");
    }
    }
    class Monkey extends Animal
    {
    public void eat()
    {
    System.out.println("我什么都吃,尤其喜欢香蕉。");
    }
    }
    class Pigeon extends Animal
    {
    public void eat()
    {
    System.out.println("我要减肥,所以每天只吃一点大米。");
    }
    }
    进一步优化喂养一群动物

    package zoo3;
    public class Zoo
    public static void main(String args[]) {
    Feeder f = new Feeder("小李");
    Animal[] ans = new Animal[16];
    //饲养员小李喂养一只狮子
    ans[0] = new Lion();
    //饲养员小李喂养十只猴子
    for (int i = 0; i < 10; i++) {
    ans[1 + i] = new Monkey();
    }
    //饲养员小李喂养5只鸽子
    for (int i = 0; i < 5; i++) {
    ans[11 + i] = new Pigeon();
    }
    f.feedAnimals(ans);
    }
    }
    class Feeder {
    public String name;
    Feeder(String name) {
    this.name = name;
    }
    public void feedAnimals(Animal[] ans) {
    for (Animal an : ans) {
    an.eat();
    }
    }
    }
    abstract class Animal {
    public abstract void eat();
    }
    class Lion extends Animal {
    public void eat() {
    System.out.println("我不吃肉谁敢吃肉!");
    }
    }
    class Monkey extends Animal {
    public void eat() {
    System.out.println("我什么都吃,尤其喜欢香蕉。");
    }
    }
    class Pigeon extends Animal {
    public void eat() {
    System.out.println("我要减肥,所以每天只吃一点大米。");
    }
    }
    第二次重构之后,Feeder类的feedAnimals()方法接收的是一个Animal数组,这有一个限制,就是只能创建固定个数的数组,无法动态地增减动物个数。

    想想以下场景:

    (1)动物园新进了一些动物

    (2)某动物生病不幸死亡

    (3)……

    我们的代码能否应付以上的场景

    import java.util.Vector;
    public class Zoo {
    public static void main(String args[]) {
    Feeder f = new Feeder("小李");
    Vector<Animal> ans = new Vector<Animal>();
    //饲养员小李喂养一只狮子
    ans.add(new Lion());
    //饲养员小李喂养十只猴子
    for (int i = 0; i < 10; i++) {
    ans.add(new Monkey());
    }
    //饲养员小李喂养5只鸽子
    for (int i = 0; i < 5; i++) {
    ans.add(new Pigeon());
    }
    f.feedAnimals(ans);
    }
    }
    class Feeder {
    public String name;
    Feeder(String name) {
    this.name = name;
    }
    //Vector<T>是JDK中提供的一个对象集合,可以随时向其中加入或移除对象
    public void feedAnimals(Vector<Animal> ans) {
    for (Animal an : ans) {
    an.eat();
    }
    }
    }
    abstract class Animal {
    public abstract void eat();
    }
    class Lion extends Animal {
    public void eat() {
    System.out.println("我不吃肉谁敢吃肉!");
    }
    }
    class Monkey extends Animal {
    public void eat() {
    System.out.println("我什么都吃,尤其喜欢香蕉。");
    }
    }
    class Pigeon extends Animal {
    public void eat() {
    System.out.println("我要减肥,所以每天只吃一点大米。");
    }
    }

    多态编程有两种主要形式:

    (1)继承多态:示例程序使用的方法

    (2)接口多态:使用接口代替抽象基类。

    使用多态最大的好处是,当你要修改程序并扩充系统时,你需要修改的地方较少,对其它部分代码的影响较小

  • 相关阅读:
    curl 空格和转义符
    supervisor
    pandas 小笔记
    bert 进行文本相似度计算
    认股权证的会计处理
    企业所得税汇算清缴
    调整事项与非调整事项的区别
    centos 挂载windows 2003 smb
    如何获得带转义的json内容
    安装了vs2019 编译node-sass node-gyp 找不到编译器的解决方法
  • 原文地址:https://www.cnblogs.com/fengjingfei/p/11723136.html
Copyright © 2020-2023  润新知