c++ lambda 重载_您会后悔对Lambdas应用重载!

c++ lambda 重载

编写好的API很难。 非常辛苦。 如果您希望用户喜欢您的API,则必须考虑很多事情。 您必须在以下两者之间找到适当的平衡:

  1. 用处
  2. 易用性
  3. 向后兼容
  4. 前向兼容性

之前,在我们的文章: 如何设计良好的常规API中,我们已经就此主题进行过博客讨论。 今天,我们将研究如何…

Java 8更改规则

ryNBGfQ

是!

重载是在两个方面提供便利的好工具:

  • 通过提供参数类型替代
  • 通过提供参数默认值

来自JDK的上述示例包括:

public class Arrays {// Argument type alternativespublic static void sort(int[] a) { ... }public static void sort(long[] a) { ... }// Argument default valuespublic static IntStream stream(int[] array) { ... }public static IntStream stream(int[] array, int startInclusive, int endExclusive) { ... }
}

jOOQ API显然充满了这种便利。 由于jOOQ是SQL的DSL ,我们甚至可能会滥用一点:

public interface DSLContext {<T1> SelectSelectStep<Record1<T1>> select(SelectField<T1> field1);<T1, T2> SelectSelectStep<Record2<T1, T2>> select(SelectField<T1> field1, SelectField<T2> field2);<T1, T2, T3> SelectSelectStep<Record3<T1, T2, T3>> sselect(SelectField<T1> field1, SelectField<T2> field2, SelectField<T3> field3);<T1, T2, T3, T4> SelectSelectStep<Record4<T1, T2, T3, T4>> select(SelectField<T1> field1, SelectField<T2> field2, SelectField<T3> field3, SelectField<T4> field4);// and so on...
}

诸如Ceylon之类的语言通过声称以上内容是在Java中使用重载的唯一合理原因,将便利性这一概念进一步提高了。 因此,锡兰(Ceylon)的创建者已完全消除了其语言中的重载,将以上内容替换为联合类型和参数的实际默认值。 例如

// Union types
void sort(int[]|long[] a) { ... }// Default argument values
IntStream stream(int[] array,int startInclusive = 0,int endInclusive = array.length) { ... }

阅读“我希望在Java中拥有的十大锡兰语言功能” ,以获取有关锡兰的更多信息。

不幸的是,在Java中,我们不能使用联合类型或参数默认值。 因此,我们必须使用重载为API使用者提供便捷的方法。

但是,如果您的方法参数是一个函数接口 ,则在方法重载方面,Java 7和Java 8之间的情况发生了巨大变化。 JavaFX在此给出一个示例。

JavaFX的“不友好”的ObservableList

JavaFX通过使它们“可观察”来增强JDK集合类型。 不要与Observable混淆, Observable是JDK 1.0和Swing之前的恐龙类型。

JavaFX自己的Observable本质上是这样的:

public interface Observable {void addListener(InvalidationListener listener);void removeListener(InvalidationListener listener);
}

幸运的是,这个InvalidationListener是一个功能接口:

@FunctionalInterface
public interface InvalidationListener {void invalidated(Observable observable);
}

这很棒,因为我们可以做以下事情:

Observable awesome = FXCollections.observableArrayList();
awesome.addListener(fantastic -> splendid.cheer());

(请注意,我是如何用更开朗的术语替换foo / bar / baz的。我们都应该这样做。Foo和bar是如此1970 )

不幸的是,当我们做我们可能要做的事情时,事情变得更加繁琐。 即,与其声明一个ObservableObservable是一个更加有用的ObservableList

ObservableList<String> awesome = FXCollections.observableArrayList();
awesome.addListener(fantastic -> splendid.cheer());

但是现在,我们在第二行收到编译错误:

awesome.addListener(fantastic -> splendid.cheer());
//      ^^^^^^^^^^^ 
// The method addListener(ListChangeListener<? super String>) 
// is ambiguous for the type ObservableList<String>

因为,本质上...

public interface ObservableList<E> 
extends List<E>, Observable {void addListener(ListChangeListener<? super E> listener);
}

和…

@FunctionalInterface
public interface ListChangeListener<E> {void onChanged(Change<? extends E> c);
}

再一次,在Java 8之前,这两种侦听器类型是完全可区分的,并且仍然是可区分的。 您可以通过传递命名类型来轻松调用它们。 如果我们编写以下代码,我们的原始代码仍然可以使用:

ObservableList<String> awesome = FXCollections.observableArrayList();
InvalidationListener hearYe = fantastic -> splendid.cheer();
awesome.addListener(hearYe);

要么…

ObservableList<String> awesome = FXCollections.observableArrayList();
awesome.addListener((InvalidationListener) fantastic -> splendid.cheer());

甚至…

ObservableList<String> awesome = FXCollections.observableArrayList();
awesome.addListener((Observable fantastic) -> splendid.cheer());

所有这些措施将消除歧义。 但坦率地说,如果您必须显式键入lambda或参数类型,则lambda的性能只有后者的一半。 我们拥有现代化的IDE,它们可以执行自动补全并帮助推断类型,就像编译器本身一样。

想象一下,如果我们真的想调用另一个addListener()方法,它需要一个ListChangeListener。 我们必须写任何

ObservableList<String> awesome = FXCollections.observableArrayList();// Agh. Remember that we have to repeat "String" here
ListChangeListener<String> hearYe = fantastic -> splendid.cheer();
awesome.addListener(hearYe);

要么…

ObservableList<String> awesome = FXCollections.observableArrayList();// Agh. Remember that we have to repeat "String" here
awesome.addListener((ListChangeListener<String>) fantastic -> splendid.cheer());

甚至…

ObservableList<String> awesome = FXCollections.observableArrayList();// WTF... "extends" String?? But that's what this thing needs...
awesome.addListener((Change<? extends String> fantastic) -> splendid.cheer());

必须警惕。

API设计很难。 以前很难,现在变得越来越难。 在Java 8中,如果您的API方法的任何参数是功能接口,请三思而后行重载该API方法。 一旦您确定要继续进行重载,请再次考虑,这是否真的是一个好主意。

不服气吗? 仔细看一下JDK。 例如java.util.stream.Stream类型。 您看到多少个具有相同数量的功能接口参数的重载方法,而这些接口又采用了相同数量的方法参数(就像我们前面的addListener()示例中一样)?

零。

在重载参数编号不同的地方有重载。 例如:

<R> R collect(Supplier<R> supplier,BiConsumer<R, ? super T> accumulator,BiConsumer<R, R> combiner);<R, A> R collect(Collector<? super T, A, R> collector);

调用collect()时,您永远不会有任何歧义。

但是,如果参数编号没有不同,并且参数本身的方法参数编号也没有变化,则方法名称也不同。 例如:

<R> Stream<R> map(Function<? super T, ? extends R> mapper);
IntStream mapToInt(ToIntFunction<? super T> mapper);
LongStream mapToLong(ToLongFunction<? super T> mapper);
DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);

现在,这在呼叫站点上非常令人讨厌,因为您必须预先考虑必须根据各种相关类型使用哪种方法。

但这确实是解决这一难题的唯一方法。 因此,请记住: 您会为Lambdas应用重载感到遗憾!

翻译自: https://www.javacodegeeks.com/2015/02/you-will-regret-applying-overloading-with-lambdas.html

c++ lambda 重载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/338161.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux1到10累加,10个有趣的 Linux 命令

在终端工作是一件很有趣的事情。今天&#xff0c;我们将会列举一些有趣得为你带来欢笑的Linux命令。1. rev创建一个文件&#xff0c;在文件里面输入几个单词&#xff0c;rev命令会将你写的东西反转输出到控制台。# revSelection_002Selection_0012. fortune这个命令没有被默认安…

7个华为关于C语言的经典面试题

1、找错void test1(){ char string[10]; char* str1"0123456789"; strcpy(string, str1);}这里string数组越界&#xff0c;因为字符串长度为10&#xff0c;还有一个结束符’\0’。所以总共有11个字符长度。string数组大小为10&#xff0c;这里越界了。PS&am…

java8 函数式编程_Java 8函数式编程:延迟实例化

java8 函数式编程单例通常会延迟实例化自己&#xff0c;有时&#xff0c;如果对象足够重&#xff0c;则可以延迟实例化类字段。 通常&#xff0c;在走惰性路线时&#xff0c;getter方法&#xff08;或accessor &#xff09;必须具有一段代码&#xff0c;该代码块在返回对象之前…

linux数组操作 增删改查,linuxea:go数组与数组增删改查(19)

复合数据类型是集合类&#xff0c;并且可以存储多个单值。在golang中存储的数组是相同的数据类型&#xff0c;并且长度也是其中的一个属性。在go中&#xff0c;数组的长度一旦定义&#xff0c;就不可变。如果声明了长度的变量&#xff0c;只能赋值相同的长度的数组数组是具有相…

C语言的特点与创建的基本步骤是什么

C语言的特点与创建的基本步骤是&#xff1a;C 语言特点&#xff1a;1.C语言是一种成功的系统描述语言&#xff0c;用C语言开发的UNIX操作系统就是一个成功的范例;2.同时C语言又是一种通用的程序设计语言&#xff0c;在国际上广泛流行。世界上很多著名的计算公司都成功的开发了不…

谷歌guava_Google Guava:您永远不会知道的5件事

谷歌guava每个开发人员可以使用哪些鲜为人知的Google Guava功能&#xff1f; 它是那里最受欢迎的库之一&#xff0c;它是开源的&#xff0c;您可能已经知道了&#xff0c;它来自人们玩Quidditch作为一项真正的运动的地方&#xff08;至少在The Internship上 &#xff09;。 它…

c语言中prime的作用,C语言判断素数prime

《C语言判断素数prime》由会员分享&#xff0c;可在线阅读&#xff0c;更多相关《C语言判断素数prime(2页珍藏版)》请在人人文库网上搜索。1、主函数&#xff1a;#include int prime();void main()int number;int flag;printf (请输入一个大于1的整数:);scanf (%d,&number)…

C语言strcmp函数用法

C语言strcmp函数用法strcmp函数语法为“int strcmp(char *str1,char *str2)”&#xff0c;其作用是比较字符串str1和str2是否相同&#xff0c;如果相同则返回0&#xff0c;如果不同&#xff0c;前者大于后者则返回1&#xff0c;否则返回-1。简单示例&#xff1a;char a[]"…

Linux C 服务器端这条线怎么走?

在校学生的编程语言和数据结构的基础还不错&#xff0c;我认为应该在《操作系统》和《计算机体系结构》这两门课上下功夫&#xff0c;然后才去读编程方面的 APUE、UNP 等书。下面简单谈谈我对学习这两门课的看法和建议&#xff0c;都是站在服务端程序员的角度&#xff0c;从实用…

tp3 默认模块 默认方法_您需要了解的有关默认方法的所有信息

tp3 默认模块 默认方法因此&#xff0c;默认方法是……昨天的新闻&#xff0c;对不对&#xff1f; 是的&#xff0c;但是使用了一年之后&#xff0c;积累了很多事实&#xff0c;我想将这些事实收集在一个地方&#xff0c;供刚开始使用它们的开发人员使用。 甚至有经验的人都可以…

熟悉c语言,实验一 熟悉C语言的运行环境

《实验一 熟悉C语言的运行环境》由会员分享&#xff0c;可在线阅读&#xff0c;更多相关《实验一 熟悉C语言的运行环境(8页珍藏版)》请在人人文库网上搜索。1、实验一 熟悉C语言的运行环境一、 实验目的1. 熟悉C语言运行环境。2. 掌握语言程序的书写格式和语言程序的结构。3. 掌…

存储过程 锁定并发_Java并发教程–锁定:显式锁定

存储过程 锁定并发1.简介 在许多情况下&#xff0c;使用隐式锁定就足够了。 有时&#xff0c;我们将需要更复杂的功能。 在这种情况下&#xff0c; java.util.concurrent.locks包为我们提供了锁定对象。 当涉及到内存同步时&#xff0c;这些锁的内部机制与隐式锁相同。 区别在于…

C语言 PK 各大编程语言

今天分享一篇关于C语言为何如此有魅力的文章&#xff0c;如果你还在学习哪门语言的路口抉择&#xff0c;建议可以认真看看~以下为CSDN译文&#xff1a;没有什么技术可以应用长达50年之久&#xff0c;除非它真的比大多数其他东西都要好用——对于一种计算机行业的技术来说尤其如…

c语言线性表拷贝,数据结构(C语言版)---线性表顺序存储表示

1、顺序表&#xff1a;线性表的顺序存储&#xff0c;用一组地址连续的存储单元存储线性表中的数据元素。1) 特点&#xff1a;随机访问&#xff0c;即通过首地址和元素序号可在时间O(1)内找到指定元素。表中元素的逻辑顺序与其物理顺序相同&#xff0c;线性表中元素的位序是从1开…

nifty ui_Nifty JUnit:在方法和类级别上使用规则

nifty ui如Nifty JUnit&#xff1a;使用临时文件一文中所示 &#xff0c;可以在JUnit测试中使用Rule &#xff0c;这是方法级别的规则。 在此示例中&#xff0c;我想显示ClassRule用于类级别规则的变体。 方法规则 Rule在测试类的每个测试方法&#xff08;就像Before &#xf…

在switch语句中,case后的标号只能是什么?

switch语句用于基于不同条件执行不同动作。语法格式&#xff1a;switch (变量表达式){case 常量1: 语句;break;case 常量2: 语句;break;case 常量3: 语句;break;...case 常量n: 语句;break;default: 语句;break;}switch语句是一个条件选择语句&#xff0c;找到相同的…

android+动画+锯齿,Android当中的防锯齿(Bitmap Canvas )

在Android中&#xff0c;目前&#xff0c;我知道有两种出现锯齿的情况。① 当我们用Canvas绘制位图的时候&#xff0c;如果对位图进行了选择&#xff0c;则位图会出现锯齿。② 在用View的RotateAnimation做动画时候&#xff0c;如果View当中包含有大量的图形&#xff0c;也会出…

osgi:install_OSGi服务测试助手:ServiceRegistrationRule

osgi:installOSGi服务测试可以是避免与悬挂的服务引用有关的问题的有效方法。 就像我在写简单服务贡献验证中所承诺的那样&#xff0c;这次我引入了一个JUnit规则 &#xff0c;该规则有助于测试组件之间的交互。 OSGi服务测试组件交互 假设我们有一个服务&#xff0c;该服务通…

C语言——结构体链表,附完整示例

引用自身的结构体&#xff0c;一个结构体中有一个或多个成员的基类型就是本结构体类型时&#xff0c;说明这个结构体可以引用自己&#xff0c;所以称作引用自身的结构体。例如下面的结构体&#xff1a;struct link{ char ch; struct link *p} a;p是一个可以指向struct link类型…

android 注解点击事件,android click事件注解

定义注解&#xff1a;package com.fyfeng.android.annotations;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;Retention(value RetentionPolicy.RUNTIME…