Java类和对象(三)

本文将关注面向对象的第三大要素:多态。文章开始先介绍多态的使用方法,然后介绍为什么使用多态。使用多态之前需要先知道三种技术

  • 继承
  • 向上转型
  • 复写(override)

我们姑且把这三种技术称为多态的三要素吧,继承已经在Java类和对象(二)里面描述过了,这里不再赘述。

向上转型

向上转型就是把子类对象转换成父类对象。因为子类继承自父类,子类对象包含了父类对象的信息,所以可以把子类对象转换为父类对象。

//向上转型示例
class Base{
    String name;
    String age;
    public void doSomeThing(){

    }
}
class Derived extends Base{
    String another;
}
public class TestClass {
    public static void main(String[] args){
        Derived d = new Derived();
        //向上转型
        Base b = d;
        b.doSomeThing();
    }
}

复写(override)

子类可以复用父类的方法实现,也可以重新实现方法,但是方法签名必须和父类一致,这里的重新实现就是复写。

//复写示例,复写doSomeThing方法
class Base{
    public void doSomeThing(){
        System.out.println("in Base");
    }
}
class Derived extends Base{
    public void doSomeThing(){
        System.out.println("in Derived");
    }
}

使用多态

看下面的多态使用示例

//多态的使用示例
class Base{
    public void doSomeThing(){
        System.out.println("in Base");
    }
}
class Derived extends Base{
    public void doSomeThing(){
        System.out.println("in Derived");
    }
}
public class TestClass {
    public static void main(String[] args){
        Derived d = new Derived();
        Base b = d;
        b.doSomeThing();//多态,输出in Derived
    }
}

上例中doSomeThing方法被复写了,Derived对象向上转型为Base对象以后,使用Base对象调用doSomeThing方法输出“in Derived”,如果没有复写它的输出应该是“in Base”。多态表达的意思是子类可以通过复写方法拥有自己的定制行为,且可以通过向上转型为父类对象来调用,这样每个子类的调用方式是一致的,但是表现出来的行为却各不一样。

//多态解释
package example;

class Base{
    public void doSomeThing(){
        System.out.println("in Base");
    }
}
class Derived1 extends Base{
    public void doSomeThing(){
        System.out.println("in Derived1");
    }
}
class Derived2 extends Base{
    public void doSomeThing(){
        System.out.println("in Derived2");
    }
}
public class TestClass {
    static void doSomeThing(Base b){
        //调用形式都一样
        b.doSomeThing();
    }
    public static void main(String[] args){
        Derived1 d1 = new Derived1();
        Derived2 d2 = new Derived2();
        doSomeThing(d1); //输出in Derived1
        doSomeThing(d2); //输出in Derived2
    }
}

看TestClass的doSomeThing方法,不管是对象d1还是d2调用形式都是b.doSomeThing,但是调用的结果却不一样。注意如果Derived1和Derived2没有复写doSomeThing方法,上例中两次调用doSomeThing(Derived)的输出都将是in Base。

为什么使用多态

假设我们在开发一个游戏,实现移动一群NPC(非玩家角色 Non-Player Character )的需求,每个NPC都继承自Spirit类,且每个NPC移动的动画不一样,在不使用多态的情况下怎么实现这种需求?一种实现方式如下:

class Spirit{
    //回血
    public void plusBlood(){

    }
}
//乔峰
class Qiaofeng extends Spirit{
    public void move(){
        System.out.println("乔峰移动动画");
    }
}
//段誉
class Duanyu extends Spirit{
    public void move(){
        System.out.println("段誉移动动画");
    }
}
//
//......还有很多NPC
//
public class TestClass {
    public static void main(String[] args){
        Qiaofeng qiaofeng = new Qiaofeng();
        Duanyu duanyu = new Duanyu();
        //......这里还有其它n个NPC
        
        qiaofeng.move();
        duanyu.move();
        //....每个NPC调用move方法
    }
}

可以看到我们需要实例化每一个NPC对象,然后对每个对象调用move方法,这种实现方式的问题在于如果NPC数量很多的时候代码量将非常庞大。如果使用多态将减少很多代码,使用多态后的代码如下:

//多态实现方式
class Spirit{
    //回血
    public void plusBlood(){

    }
    public void move(){
        System.out.println("通用移动动画");
    }
}
//乔峰
class Qiaofeng extends Spirit{
    public void move(){
        System.out.println("乔峰移动动画");
    }
}
//段誉
class Duanyu extends Spirit{
    public void move(){
        System.out.println("段誉移动动画");
    }
}
//
//......假设还有很多NPC
//
public class TestClass {
    static void move(ArrayList<Spirit> spirits){
        for (Spirit s:spirits) {
            s.move();
        }
    }
    public static void main(String[] args){
        ArrayList<Spirit> spirits = new ArrayList<>();
        spirits.add(new Qiaofeng());
        spirits.add(new Duanyu());
        //......这里还有其它n个NPC
        move(spirits);
    }
}

我们把move方法移动到Spirit类里面,子类复写move方法。同样的我们需要实例化每一个对象,不同的是我们把每个对象放到容器spirits里面,然后遍历容器调用move方法。多态实现不用每个对象都调用move方法,减少了调用move方法的代码量。通过比较可以总结出多态有两个优点

  • 合理的多态使用可以减少代码量
  • 抽象编程

减少代码量的优点在例子中可以明显的看到,抽象编程则不容易看到,我们将在下一篇文章中学习抽象编程。

最后

多态包含三个要素:继承、向上转型、复写。使用多态可以使用抽象编程,可以减少代码量,我相信没有程序员愿意多写代码,特别是重复无聊的代码。

 

 

【水煮Java】

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值