B2 · 第2集 · 5:01

Java匿名类与函数式接口

本集讲解Java中如何用匿名类和函数式接口模拟JavaScript的事件处理机制。

来源:Nicolas Hurtubise / classe.iro.umontreal.ca · 许可:CC BY-SA 4.0

字幕

  1. à la fonction qui charge de regarder quoi faire quand il y a un événement.

    一个用于处理事件发生时该做什么的函数。

  2. On pourrait définir ce genre de choses- là pour toutes sortes d'événements.

    我们可以为各种事件定义这类东西。

  3. Mettons qu'on est intéressé à afficher bonjour dans la console quand

    假设我们想在控制台中显示‘你好’,当

  4. quelqu'un presse sur la touche espace en particulier, on

    某人特别按下空格键时,我们

  5. pourra enregistrer un événement lors du key up,

    可以注册一个按键松开事件,

  6. puis à ce moment- là, le code exécuté dans le cas où cet événement- là survient,

    此时,一旦该事件发生,就会执行以下代码:

  7. c'est le code suivant, c'est appeler la fonction qui va regarder si le code de

    调用一个函数,检查

  8. l'événement c'est bien la touche espace qui a été appuyée.

    该事件的键码是否确实是空格键。

  9. Si c'est le cas, ben on affiche bonjour.

    如果是,就显示‘你好’。

  10. Fait que ok, ça c'est ce qu'on peut faire en JavaScript.

    好的,这就是 JavaScript 中可以做到的。

  11. Maintenant en Java, en

    现在来看 Java——

  12. Java c'est malheureusement pas comme ça que ça fonctionne.

    不幸的是,Java 并不是这样工作的。

  13. En Java, les fonctions ne sont pas des objets.

    在 Java 中,函数不是对象。

  14. À peu près tout en Java est un objet, mais

    Java 中几乎一切都是对象,但

  15. les fonctions font pas partie de ça.

    函数并不属于这一类。

  16. Les fonctions sont des procédures stockées dans l'ordinateur d'une façon ou d'une

    函数是存储在计算机中的某种程序,

  17. autre, mais Java ne modélise pas les fonctions comme quelque chose qu'on peut mettre

    但 Java 并不把函数建模为

  18. dans une variable, passer en paramètre à d'autres choses,

    存入变量、作为参数传给其他方法,

  19. retourner comme valeur. Vraiment les fonctions c'est quelque chose de spécial en

    或作为返回值返回。实际上,在 Java 中,函数是特殊的存在,

  20. Java qui peut pas être utilisé

    无法被用来

  21. pour passer n'importe où n'importe quand.

    随时随地传递到任意位置。

  22. Maintenant qu'on essayait d'exécuter ce code- là ici,

    现在,如果我们尝试运行这段代码——

  23. mettons qu'on avait la fonction direBonjour qui est définie similairement à l'autre

    假设我们已定义了类似之前那样的 sayHello 函数,

  24. de tantôt, direByeBye qui est définie similairement à l'autre de tantôt,

    以及类似之前那样的 sayByeBye 函数,

  25. on pourrait pas faire quelque chose dans ce style- là.

    我们就无法写出这种风格的代码。

  26. On peut pas assigner directement la

    我们无法直接将

  27. fonction qui a contenu dans direBonjour à une variable.

    包含在direBonjour中的函数赋值给一个变量。

  28. C'est pas quelque chose qui marche en Java,

    这在Java中行不通,

  29. c'est pas quelque chose qui fonctionne avec le modèle de Java.

    也不符合Java的编程模型。

  30. Fait que pour faire la programmation événementielle,

    因此,要实现事件驱动编程,

  31. ce modèle- là ici est très pratique.

    这种模型就非常实用。

  32. Dans le fond, ce modèle- là est très flexible,

    本质上,这种模型非常灵活:

  33. on a juste à définir des événements,

    我们只需定义各种事件,

  34. puis donner une valeur qui contient en fait la fonction qu'on veut exécuter selon

    然后为每个事件指定一个值——

  35. l'événement qui s'est produit.

    该值实际就是我们要在对应事件触发时执行的函数。

  36. Dans le cas de l'événement click, on veut exécuter cette fonction- là.

    比如点击事件发生时,我们要执行这个函数。

  37. Dans le cas de l'événement keyup, on

    而当键盘按键抬起事件发生时,

  38. veut exécuter cette fonction- là.

    我们要执行另一个函数。

  39. Bien, pour faire de la programmation événementielle en Java,

    那么,在Java中实现事件驱动编程——

  40. comme ce qu'on va faire avec les interfaces graphiques,

    比如我们后续要做的图形用户界面开发——

  41. Il nous faut une façon de faire ça quand même.

    我们仍然需要一种可行的方法。

  42. Puis dans le fond, même si cette syntaxe- là directement est pas légale en Java,

    事实上,尽管这种语法在Java中不合法,

  43. même si ce truc- là directement est pas possible, on

    尽管这种方式在Java中根本不可行,

  44. peut se débrouiller d'une autre façon grâce aux autres mécanismes que Java nous

    我们仍可通过Java提供的其他机制

  45. propose, comme les interfaces puis l'héritage.

    比如接口和继承,来巧妙解决。

  46. Mettons qu'on se définit une interface qui permet de représenter une fonction.

    假设我们定义一个接口,用来表示一个函数。

  47. puis qu'on se définit dans le fond que cette interface là a une seule méthode qui

    再规定这个接口只包含一个方法,

  48. est execute avec les bons arguments en paramètres

    名为execute,且参数类型正确。

  49. ben on pourrait aller se faire deux classes carrément qui vont chacune implémenter

    那么,我们完全可以创建两个类,

  50. l'interface function Puis dans le fond,

    各自实现Function接口。

  51. ces deux classes- là vont posséder la méthode execute avec String args en paramètre.

    这两个类都将拥有带String类型参数的execute方法。

  52. Puis ces classes- là vont représenter

    然后,这些类将代表

  53. le même genre d'objet qui nous permet de

    同一类对象,使我们能够

  54. contenir une fonction, de représenter une fonction.

    封装一个函数,即表示一个函数。

  55. Dans le fond, n'importe quelle instance de DireBonjour, quand on va

    本质上,任意一个 DireBonjour 实例,当我们

  56. exécuter sa méthode execute avec un certain paramètre,

    用某个参数调用其 execute 方法时,

  57. ben ça va exécuter ce code- là.

    就会执行那段代码。

  58. N'importe quelle instance de DireByeBye va plutôt exécuter ce code- là.

    而任意一个 DireByeBye 实例,则会执行另一段代码。

  59. Puis les deux implémentent

    并且,这两者都实现了

  60. la même interface, donc c'est deux trucs qui sont compatibles.

    同一个接口,因此它们是兼容的。

  61. On pourrait aller se faire de quoi de ce style- là.

    我们可以这样来实现:

  62. on pourrait aller se définir une variable de type notre interface Function,

    比如定义一个类型为 Function(我们的接口)的变量,

  63. puis aller faire de quoi de similaire à mon exemple de tout à l'heure où on avait

    再像刚才 JavaScript 示例那样操作:

  64. une chance sur deux d'avoir une fonction,

    有 50% 的概率得到这个函数,

  65. une chance sur deux d'avoir l'autre fonction.

    也有 50% 的概率得到另一个函数。

  66. Dans le fond, plutôt que de mettre une fonction dans notre variable,

    本质上,我们不是把函数直接存入变量,

  67. on met soit une instance de telle affaire,

    而是存入某类对象的一个实例,

  68. soit une instance de telle autre affaire,

    或是另一类对象的一个实例,

  69. puis à la fin on exécute la méthode qui représente dans le fond ce que cet objet- là

    最后调用该对象所代表的方法——

  70. doit faire. Donc, ça marche, ça fait ce qu'on faisait avec la programmation

    也就是该对象应执行的操作。

  71. fonctionnelle en JavaScript tout à

    所以,这种方式可行,效果和之前 JavaScript 中的函数式编程一样。

  72. l'heure. mais c'est quand même lourd

    但在这里,实现同样功能却显得很繁琐。

  73. ici dans le fond pour arriver à faire la même chose que ce qu'on faisait dans le

    与前面 JavaScript 第一个示例相比,

  74. premier exemple en JavaScript dans le fond pour faire ce qu'on avait à

    我们要完成同样的任务,却需要更多步骤。

  75. Cette page- là ici, ben ici

    就这一页而言,

  76. on a à peu près une dizaine de lignes de JavaScript, 10 ou 15,

    JavaScript 代码大约只有十行左右,最多十五行。

  77. alors qu'ici ben on a quatre fichiers, trois classes, une interface,

    而这里呢?我们却要创建四个文件:三个类、一个接口。

  78. là- dedans on a deux classes qui sont instanciées une seule fois dans tout le

    其中两个类在整个程序中仅被实例化一次,

  79. programme, c'est lourd, c'est pas pratique.

    实在过于繁琐,也不够实用。

  80. Fait que pour simplifier tout ça,

    为了简化这一切,

  81. on peut profiter d'un concept en Java qui est le concept de classe anonyme.

    我们可以利用Java中的一个概念——匿名类。

  82. Dans le fond, en Java, une classe anonyme,

    本质上,在Java中,匿名类

  83. c'est une classe qui va être instanciée tout de suite sur le coup.

    是一种会立即被实例化的类。