首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

函数扩展

作者 | 杨洋

杏仁Java程序员,关注后端和底层技术

背景

最近有同事反应,我们运营后台下载的 CSV 文件出现错乱的情况。问题的原因是原始数据中有 CSV 中非法的字符,比如说姓名字段,因为是用户填写的,内容有可能包含了、等字符,会导致 CSV 文件内容错乱。于是我就想用一个简单的方式来解决这个问题。一个简单粗暴的解决方案就是导出时对字符串进行处理,将一些特殊字符替换掉,或者前后用包起来。但是这样的话,需要所有下载 CSV 的地方都要改写,会比较麻烦。如果我们可以简单的给 String 增加一个方法(如)直接就把字符串处理成 CSV 兼容的格式,就会方便很多。我们的运营后台是使用 Scala 语言开发的,所幸的是,Scala 里提供了一个非常强大的功能,可以满足我们的需求,那就是隐式转换。Scala 的隐式转换在 Scala 里可以通过隐式转换来实现函数扩展。编译器在碰到类型不匹配或是调用一个不存在的方法的时候,会去搜索符合条件的隐式类型转换,如果找不到合适的隐式转换方法则会报错。下面是处理 CSV 下载字符串的代码:

在中我调用方法,但是没有方法。这时候编译器就会去找中有没有隐式转换的方法,发现在其父类中有方法把转换成,而中实现了方法。所以编译器最终会调用到这个方法。隐式转换是一个很强大,但是也很容易误用的功能。Scala 里隐式转换有一些基本规则:

优先规则:如果存在两个或者多个符合条件的隐式转换,如果编译器不能选择一条最优的隐式转换,则提示错误。具体的规则是:当前类中的隐式转换优先级大于父类中的隐式转换;多个隐式转换返回的类型有父子关系的时候,子类优先级大于父类。

隐式转换只会隐式的调用一次,编译器不会调用多个隐式方法,不会产生调用链。

如果当期代码已经是合法的,不需要隐式转换则不会使用隐式转换。

Java 的动态扩展我们再来看看我们熟悉的 Java 语言。Java 是一门静态语言,本身没有直接提供动态扩展的方法,但是我们可以通过 AOP 动态代理的方式来修改一个方法,从而间接的实现方法的动态扩展。下面就是一个我们就用来实现一个动态扩展,用于分页查询后获取数据的总条数。

其中注解表明在被注解方法返回后的一些后续动作。定义切点的表达式,可以用通配符表示;指定返回的参数名。然后就可以对返回的结果进行处理。这样就可以达到动态的修改原始函数功能。当然除了也可以使用来代理来实现简单的 AOP。

创建一个对象用来模拟查询分页方法。

创建一个代理类实现接口,手动调用方法,用来动态的修改被代理的实现方法。可以在执行之前做一些参数校验,或者一些参数的预处理。也可以获取修改执行的结果,或者干脆不调用方法,自定义实现。也可以在调用后做一些后续动作。

最后打印的输出是:

当然除了 CGLIB 代理也可以使用 Proxy 动态代理,同样的逻辑也可以达到动态的修改原始方法的目的,从而间接的实现函数扩展。不过 Proxy 动态代理是基于接口的代理。其它语言的函数扩展其实除了 Scala 的隐式转换和 Java 的动态代理,其他很多语言也能支持各种不同的函数扩展。Swift在 Swift 中可以通过关键词对已有的类进行扩展,可以扩展方法、属性、下标、构造器等等。

比如说我给 Int 增加一个 times 方法。即执行任务的次数。就可以如下使用:

上面的代码会执行 2 次打印方法。Go在 Go 中可以通过在方法名前面加上一个变量,这个附加的参数会将该函数附加到这种类型上。即给一个方法加上接收器。

KotlinKotlin 的函数扩展非常简单,就是定义的时候,函数名写成++就行了。

注意当给一个类扩展已有的方法的时候,默认使用的是类自带的成员函数。如下:

可以通过函数重载的方式区分成员函数(),在调用的地方显示的区分。JavaScript在 JavaScript 中也可以很方便的给一个对象扩展函数。写法就是++。

也可以给一个 Object 进行扩展:

总结

其实了解不同语言对于函数扩展的实现挺有意思的,本文只是粗略的介绍了一下。合理的使用这些语言的扩展,可以帮助我们提高代码质量和工作效率。我们还可以通过函数扩展来对第三方类库进行修改或者扩展,从而更灵活的调用第三方类库。

全文完

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180411G1DMFF00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券