【java杂谈】Java中的多态

🥖多态是什么?

w3school上对多态是这样描述的:

Polymorphism means "many forms", and it occurs when we have many classes that are related to each other by inheritance.

实际上,多态就是“多种形式”,它具有以下两层意义:

  • 多态是同一个行为具有不同的表现形式或形态的能力

  • 同一方法可以根据发送对象的不同而采用不同的行为方式

多态具有三种类型:

  • Ad hoc polymorphism (特殊多态)

  • Parametric polymorphism (参数化多态)

  • Subtyping (also called subtype polymorphism or inclusion polymorphism 子类型多态、包含多态)

接下来,我将对三种多态逐一分析:

🫓多态的三种类型:

🚝Ad hoc polymorphism (特殊多态)

这种多态发生在方法具有不同的实现时,在常见的编程语言中常常通过方法重载(overloading)实现。

public class OverloadExample {

            public static String add(String c, String d) {
                return c.concat(d);
            }

            public static String add(String c, String d, String e) {
                return c.concat(d).concat(e);
            }

            public static int add(int a, int b) {
                return a + b;
            }
        }

在上述代码中,add()方法具有多种实现,他们的参数列表不同(包括参数的数量不同以及参数的数据类型不同,但不包括参数名称不同),编译器会将其视作不同的方法。

在具体使用add()方法时,根据参数的不同,会调用相应的方法:

public static void main(String args[]) {
    System.out.println(add("C", "D"));
    System.out.println(add("C", "D", "E"));
    System.out.println(add(2, 3));
}

值得注意的是,方法的重载也可以发生在子类和父类中,观察下面的例子:

class Animal {
        public void eat() {
        }
    }

    class Horse extends Animal {
        public void eat(String food) {
        }
    }

在这个例子中,子类Horse重载了父类的eat()方法,相当于:

class Animal {
        public void eat() {
        }
    }

    class Horse extends Animal {
        public void eat() {
        }

        public void eat(String food) {
        }
    }

将其实例化,调用eat()方法,会有以下结果:

        Animal a = new Animal();
        a.eat();
        a.eat("food");//编译报错,因为Animal类没有eat(String food)方法

        Animal b = new Horse();
        b.eat();
        b.eat("food");//编译报错,因为在编译阶段对象b会被视作一个Animal类,报错原因同上

        Horse c = new Horse();
        c.eat();
        c.eat("food");

对象b会被视作一个Animal类。

最后,给出方法重载(Overloading)与方法重写(Overriding)的区别:

🚞Parametric polymorphism (参数化多态)

参数化多态就是函数工作过程中的数据结构支持多种类型,在Java中通常使用“泛型”来实现。

在Java中有以下几种泛型:

  • 泛型变量

  • 泛型类

  • 泛型接口

  • 泛型方法

我们逐一分析:

🐳泛型变量:

见如下例子:

public class GenericClass<T>{
    //t是一个泛型成员变量
    private T t;
  
    public  void function(T t){

    }

在这个例子中T是一个泛型变量,这意味着T可以是任意的引用数据类型(详情可见笔者博文:数据类型与类型检验)。

🐋泛型类:

//GenericClass是一个泛型类
public class GenericClass<T>{
    //t是一个泛型成员变量
    private T t;
  
    public  void function(T t){

    }

仍然是刚刚的例子,GenericClass类在声明时添加了<T>这就是说,这个类是一个泛型类,具有一个泛型T。类的泛型也可以有多个,语法为:

[访问修饰符] class 类名<泛型1,泛型2,...> {
    泛型1 泛型成员1 ;
    泛型2 泛型成员2;
    ...
}

🐬泛型接口:

类似于泛型类,就是在接口上定义泛型,作用于方法:

public interface GenericInterface<T> {
    
    public T get();
    
    public void set(T t);

    public T delete(T t);
    
    default T defaultFunction(T t){
        return t;
    }
}

🐟泛型函数:

写法是函数返回类型旁加上泛型,用于实现一个通用数据类型的函数:

public class GenericFunction {

    public <T> void function(T t) {
    }

    public <T> T functionTwo(T t) {
        return t;
    }

    public <T> String functionThree(T t) {
        return "";
    }
}

🚋Subtyping Polymorphism(子类型多态或包含多态)

Java中的“子类”、“父类”等概念也是多态的体现。

一个子类对象B一定是“父类”(包括对接口的实现,下同),举个例子,若子类“猫”继承自父类“动物”,则“猫”的实例B一定是“动物”。

另一方面,这种子类与父类间的继承关系要求子类的Spec一定要强于其父类的Spec。

以Collection为例:

ArrayList、LinkedList一定是List,其Spec一定要强于List的Spec(显然,这是符合客观世界规律的)。

🥨多态的作用

最后,让我们再来复盘下多态,讲讲为什么要这样设计。

多态就是“多种形式”,它具有以下两层意义:

  • 多态是同一个行为具有不同的表现形式或形态的能力

  • 同一方法可以根据发送对象的不同而采用不同的行为方式

这一设计思想是符合客观世界规律的,其具有以下作用:

  • 提高了代码的维护性(继承保证)。

  • 提高了代码的扩展性(由多态保证)。

  • 泛型使程序员能够实现通用算法,增强了代码的复用。

  • 通过使用泛型,程序员可以实现适用于不同类型集合的泛型算法,安全且易于阅读。

  • 使得代码更为灵活

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值