多态与HoFs

朋友们好久不见啊,最近笔者同时在写脚本型语言——JavaScript,和工业级的面向对象语言——Java。 在写代码的同时呢,也会思考这些语言的不同。今天就拿 Java 中的多态,来谈一谈吧!

概念

多态(Polymorphism)

多态性的核心是多种表现形式。在 Java中,多态性是指对象可以拥有多种形式或者说类型。在面向对象的编程中,多态与如何将一个对象视为其自身类的实例,或者是它的父类的实例,又或者父类的父类的实例等相关。

上面那段话或许有些抽象,还是让我们举个例子吧:

假设我们拥有两个类:

SLList 类和 VengefulSLList 类,

其中 VengefulSLList类继承自 SLList 类。并覆写(override)了, removeLast 方法(method)。

我们运行以下代码:

结果:

sl.addLast(50) ; //VengefullSLList没有覆写,调用的是父类(即SLList)的方法

sl.removeLast(); //调用的是自己覆写的 removeLast( ) 方法!

再看一个例子:

public static void main(String[] args){

VengefullSLList s1 = new VengefullSLList<>(9);

SLList s2 = new SLList<>(8);

s1.removeLast(); // 调用覆写的方法

s2.removeLast(); // 调用 SLList类的方法

}

事实说明,即使是调用同一个方法,根据对象的不同,其产生的结果是多种多样的!而且,每个对象也能展现不同的类型。

HoF

Higher Order Function: A function that treats another function as data.

高级函数: 是指一个函数把其他函数当成数据。

例如 JavaScript 中的 function 就是一个 对象,可以当做参数传递。

在 Python 中我们可以这样来运用它:

def tenX(x):

return 10*x

def do_twice(f, x):

return f(f(x))

print(do_twice(tenX, 2))

# 200

然而在 Java 中我们没见过这样的用法,这是因为在 jdk8 以前 Java是禁止将函数当参数传递的!

问题

那么问题来了,如果 Java不允许 HoF 的存在,我们怎么解决这类问题呢?

例如比较大小:

def print_larger(x, y, compare, stringify):

if compare(x, y):

return stringify(x)

return stringify(y)

# HoF 模式

def print_larger(x, y):

if x.largerThan(y):

return x.str()

return y.str()

# Subtype Polymorphism 模式

# 子类的多样性

我们主要说说第二种方式:

在代码中,我们为每个对象提供了 largerThan()的方法,通过调用它实现比大小。但是在 Java中,如果我们想要实现比较各种类型的对象大小的方法呢?比如说,我们要比较企鹅的大小,我们就要实现 企鹅类的 largerThan()方法。我们要比较海豹的大小,就要实现 海豹类的largerThan()方法,。。。。。。

我们发现如果直接实现子类的方法,我们无法实现通用的比较方案,在 C++中我们可以使用重载操作符,在JS中我们可以传入 compare函数。那么我们在Java中如何实现呢?

Comparable接口

前面我们提到了多态,有时候我们调用同名的方法,也会得到不同的结果。我们可以利用这种特性,来构造一个 compareTo() 方法。

在 Java中,我们有一个接口(interface) , 叫做 Comparable 。

它规定了所有要实现该接口的类,要实现它的 compareTo(T obj) 方法。

通过接口,我们也可以巧妙的实现,对各种类型的对象,提供一个通用的解决方法!

比如我们要实现一个自己的 Util类,里面有一个 max(Comparable[] items )方法,它的功能是,返回给定的对象数组中最大的那个对象。

这里我们使用 Dog类做演示:

项目目录:

我们实现了三个类,分别是 Dog,Util,Util

代码如下:

public class Dog implements Comparable {

private int size; // 尺寸

private String name; // 名字

public Dog(){}

public Dog(int size, String name){

this.name = name;

this.size = size;

}

public void bark(){

System.out.println("My name is "+this.name+"!");

}

@Override

public int compareTo(Dog other) { // 覆写的compareTo()方法

return this.size - other.size;

}

}

public class Util {

public static Comparable max(Comparable[] items){

int maxIndex=0;

// 遍历找出size最大的狗

for (int i = 0; i < items.length; i++) {

int cmp = items[i].compareTo(items[maxIndex]);

if(cmp>0){

maxIndex = i;

}

}

return items[maxIndex];

}

}

public class LaunchDog {

public static void main(String[] args) {

Dog alice = new Dog(8,"alice");

Dog ben = new Dog(12,"ben");

Dog karn = new Dog(6,"karn");

Dog[] dogs = new Dog[]{alice,ben,karn};

// 调用 max() 方法

Dog d =(Dog) Util.max(dogs);

d.bark();

}

}

最后的输出结果为:

My name is ben!

总结

通过分析以上代码,我们发现只要是 实现了 Comparable 接口的类都可以轻松使用 Util类中的 max() 方法选出最大的项。而在 Java 中我们的 集合框架就实现了 Comparable接口,拿来即用,十分方便。

所以,在项目中我们可以利用 接口(interface) , 来实现 在脚本语言中用 HoF 实现的功能。这体现了 Java的多态。

总结,Java通过提供接口 赋予了我们使用回调的能力。

To summarize, interfaces in Java provide us with the ability to make callbacks. Sometimes, a function needs the help of another function that might not have been written yet (e.g. max needs compareTo). A callback function is the helping function (in the scenario, compareTo).

refer:

java中的多态_Java中的多态相关推荐

  1. java变量存储位置_java 中变量存储位置的区别

    [原文] 1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量 ...

  2. java可以多重继承吗_Java中的多重继承与组合vs继承

    java可以多重继承吗 有时我写了几篇有关Java继承,接口和组成的文章. 在这篇文章中,我们将研究多重继承,然后了解组成优于继承的好处. Java中的多重继承 多重继承是创建具有多个超类的单个类的能 ...

  3. java中有没有栈_Java中堆和栈有什么区别

    stack 和 heep 都是内存的一部分stack 空间小,速度比较快, 用来放对象的引用heep 大,一般所有创建的对象都放在这里.栈(stack):是一个先进后出的数据结构,通常用于保存方法(函 ...

  4. java 静态资源变量_Java中读取配置文件中的内容,并将其赋值给静态变量的方法...

    项目开发中某个功能需要抽取成方法写成一个工具类,提供给别人使用.写过工具类的人都知道,工具类中的方法一般都是静态方法,可以直接使用类名点方法名调用, 使用很方便,比如判断某个对象是否为空的方式Obje ...

  5. java 删除list元素_JAVA中循环删除list中元素的方法总结

    印象中循环删除list中的元素使用for循环的方式是有问题的,但是可以使用增强的for循环,然后今天在使用时发现报错了,然后去科普了一下,再然后发现这是一个误区.下面就来讲一讲..伸手党可直接跳至文末 ...

  6. java和equals区别_JAVA中==与equals的区别

    equals如果没有被重写的话,和==的作用是一样的,都是判断两个对象引用是否指向同一个地址.一般重写了equals()方法就表示比较它们"实际意义上相等",比较的是内容,而不是引 ...

  7. java为什么要初始化_JAVA中到底要怎么样初始化

    Java中的变量作用范围: 1. 类的属性,或者叫值域 2. 方法里的局部变量 3. 方法的参数 对于第一种变量,Java虚拟机会自动进行初始化.如果给出了初始值,则初始化为该初始值.如果没有给出,则 ...

  8. java中hashcode作用_Java中hashCode的作用

    以下是关于HashCode的官方文档定义: hashcode方法返回该对象的哈希码值.支持该方法是为哈希表提供一些优点,例如,java.util.Hashtable 提供的哈希表. hashCode  ...

  9. java 基本类型 引用_java中 引用类型 和 基本类型 有何区别?

    栈与堆都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. Java的堆是一个运行时数据区,类的(对象从中分配空间.这些对象通过new.newa ...

  10. java .this的用法_JAVA中this用法小结

    Java中的this随处可见,用法也多,现在整理有几点: 1. this是指当前对象自己. 当在一个类中要明确指出使用对象自己的的变量或函数时就应该加上this引用.如下面这个例子中: 1 publi ...

最新文章

  1. 数据处理压力中的自我拯救
  2. linux下源码安装rabbitMq
  3. go导入私有仓库中的包配置方法
  4. Golang 入门 : 数组
  5. puppet 安装mysql_Puppet安装dashboard
  6. Visual Basic .NET处理Excle表格全接触
  7. 张正友标定法公式详细推导
  8. ip命令手册: 使用iproute2工具进行路由表管理和路由策略管理
  9. Python运行时报错 ModuleNotFoundError: No module named ‘exceptions‘
  10. python-excel-openpyxl读取数据---更新完善--1
  11. Linux命令_搜索文件
  12. 拓端tecdat|R语言实现LDA主题模型分析网购数据
  13. python在科学计算中的应用_Python在科学计算中的应用
  14. 百度文库f12免费复制文章
  15. chrome自动代理检测(这玩意并没什么用,还会影响你访问某些网页)
  16. ALPS磁式传感器和轴地磁式传感器
  17. eclipes error
  18. 区分java的三大版本:JavaSE、JavaME、JavaEE
  19. CSS——CSS定位※ ( position )
  20. 计算机屏幕尺寸像素点距概念,电脑屏幕分辨率多少比较好

热门文章

  1. Kaggle金牌拿Offer有多简单?
  2. 百度某员工抱怨:前人代码写得像坨*,颠覆了对大厂的认知
  3. 华为为什么要“囤”700名数学家?中科院院士告诉你!
  4. 卧槽!看不懂这些动图,你不配做个程序员
  5. 一文读懂深度学习中的矩阵微积分
  6. 2019年9月全国程序员工资统计,看看你拖后腿了没?
  7. 最新离婚大数据曝光:所有的分手,都是蓄谋已久
  8. Linux内核网络栈1.2.13-网卡设备的初始化流程
  9. spring boot--最基础的hello world
  10. 网络工程师_想要记录下来的一些题_2