Scala 中方法扩展实践
前言
这个名字不知道取得是否合适,简单来说要干的事情就是给某个类型添加一些扩展方法,此场景在各种语言中都会用到,比如 C# 语言,如果我们使用一个别人写好的类库,而又想给某个类库添加一些自己封装的方法,最好的方式就是使用扩展方法,具体实现方式此处不赘述。
起初,我以为在 Scala 中也是这样使用的,但是直到今天我才恍然大悟,在 Scala 中扩展方法其实不是那么简单,此处说的不简单主要说的是实现的意义不简单,而不是实现方法。本文对此进行简单介绍。
一、 实现方法
首先,来说明实现方法,正如上文所说,在 Scala 中其实实现起来也很容易。
首先我们有一个要扩展的类型假定为 C,定义如下:
trait A {
def play = println("play")
}
就是这么简单的一个类,包含一个 play 方法,当然可以有各种各样的子类继承于他,及包含其他方法。
第二步,定义一个扩展方法的类型:
trait BB[+T] {
def self: T
}
此类用于包装我们的被扩展类型,其中 self 就是一个要扩展类型的实例。(此处名字取 BB 实非本意,不知是 scala bug 还是其他问题,如果此处只使用 B 来命名,下面会报错,有知情者烦请指点一二。)
第三步,定义一个 trait 继承自 BB:
trait C extends BB[A] {
def draw = self.play
}
此类型里可以定义一系列的方法,这些方法就是即将被扩展的方法,我们可以直接使用 self 来表示被扩展的对象实例,可以直接调用他的方法。
第四步,实现一个隐式类型,将 A 对象隐式转换为 C:
implicit class D(val self: A) extends C
最终,我们可以直接对 A 对象的实例调用扩展方法:
new A {}.draw
二、分析
思路缜密,逻辑清晰((*_*)),实现起来很容易。开始的时候我以为就是这样,所以为每个类型写了一堆的扩展方法,自我感觉良好,调用起来很方便。
但是这个地方有个问题,既然我们自己定义了类型A,为什么不直接将 draw 方法也写到这里面呢,瞎折腾啥,我之前是这么想的,也是这么用的。然而,今天我突然意识到一个问题,在我使用的一个类库中,很多自己定义的类型也采用此种方式定义了大量的扩展方法,那我就纳闷了,为什么不直接写到类型的定义中呢?
沉思半天,我恍然大悟,这是一种良好的封装方法。简单说来就是 A 这个类型可能包含了大量的不同种类的方法,比如对于地理信息系统来说,一个瓦片可以包含投影、裁剪、切割等多种种类的方法,每个种类可能包含了一系列方法,所以采用这种方式的好处就是可以将这些不同种类的方法放到不同的扩展类型中进行管理,实现良好的封装。并且在后续调用中,无需判断此对象是否是 A 对象,只要判断此对象是否是 C 对象即可直接调用 C 中的方法,这样就对功能实现了良好的划分。
三、结束
看似一个简单的扩展方法,也有如此多的深层次逻辑,还是需要学会思考、深入的思考,这样才能发现更多 coding 中美的地方。
Scala 中方法扩展实践的更多相关文章
- jquery中方法扩展 ($.fn & $.extend) 学习笔记
A.$.fn 1.$.fn.method() 函数为jQuery对象扩展一个属性和方法(主要用于扩展方法) :method 为自定义方法名 ($.fn 等效 $.prototype) $.fn.bor ...
- Scala中 object 和 class的区别
object 在scala中没有静态方法和静态字段,所以在scala中可以用object来实现这些功能,直接用对象名调用的方法都是采用这种实现方式,例如Array.toString.对象的构造器在第一 ...
- Scala中使用implict 扩展现有类的方法
Scala中implict的一种用法就是扩展现有类的方法,有点类似于.Net中的扩展方法(MS对扩展方法的介绍:扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改 ...
- C#中的扩展方法
扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型. 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用. 以上是msdn官网对扩展方 ...
- scala调用java的方法,返回了一个对象链表List<Student>,在scala中遍历该链表获取指定Student的名字name
假设Student类如下: class Student { private int no; private String name; public int getNo() { return no; } ...
- C#3.0中的扩展方法
在实际应用中,开发者完成代码的编译后,除非重新编译更改后的代码,否则开发者很难在原有代码中添加新的功能. 在C#3.0中,提供了一个扩展方法的新特性,可以使得开发者在编译后的程序集里边添加相关的方法, ...
- 记录C#中的扩展方法
C#中的扩展方法. 系统自带的类型,我们无法去修改: 修改源代码需要较大的精力,而且可能会带来错误: 我们只是需要一个或者较少的几个方法,修改源代码费时费力: 被扩展的类是sealed的,不能被继承: ...
- C#编程(六十一)------------LINQ中的扩展方法
原文链接: http://blog.csdn.net/shanyongxu/article/details/47208401 LINQ中的扩展方法 LINQ中where扩展方法,要想使用,必须导入us ...
- Scala 中的foreach和map方法比较
Scala中的集合对象都有foreach和map两个方法.两个方法的共同点在于:都是用于遍历集合对象,并对每一项执行指定的方法.而两者的差异在于:foreach无返回值(准确说返回void),map返 ...
随机推荐
- H3C505
H3C505 1.立方体案例 2.3D变换 1)景深透视 prospective:xx px; 设置观察元素的距离,数值小时,在元素内进行观察 prospective-origin: xpx,xpx ...
- Java名称字符串进行星号处理
/** * 对字符串处理:将指定位置到指定位置的字符以星号代替 * * @param content * 传入的字符串 * @param begin * 开始位置 * @param end * 结束位 ...
- 这13个开源GIS软件,你了解几个?【转】
泰伯网有看点的空间地理信息资讯都在这,你还在等什么? 这些开源GIS软件,你了解几个?本文内容部分来源于一份罗列了关于GIS软件应用的文章,笔者将其编译整合. 地理信息系统(Geographic In ...
- Excel 驼峰表达式
=LEFT(A1,1)&MID(SUBSTITUTE(PROPER(A1),"_",""),2,100)
- java AOP Before, After, AfterReturning, AfterThrowing, or Around 注解
https://www.eclipse.org/aspectj/doc/next/adk15notebook/ataspectj-pcadvice.html Advice In this sectio ...
- [C#] 将NLog输出到RichTextBox,并在运行时动态修改日志级别过滤
作者: zyl910 一.缘由 NLog是一个很好用的日志类库.利用它,可以很方便的将日志输出到 调试器.文件 等目标,还支持输出到窗体界面中的RichTextBox等目标. 而且它还支持在运行时修改 ...
- Unity应用架构设计(6)——设计动态数据集合ObservableList
什么是 『动态数据集合』 ?简而言之,就是当集合添加.删除项目或者重置时,能提供一种通知机制,告诉UI动态更新界面.有经验的程序员脑海里迸出的第一个词就是 ObservableCollection.没 ...
- 使用PIP扩展BTARN
下载安装部署 从GS1 US RosettaNet下载相应的PIP文件  新建BizTalk解决方案并设置签名 添加->现有项(C:\Program Files (x86)\Microsoft ...
- Django Rest Framework(认证、权限、限制访问频率)
阅读原文Django Rest Framework(认证.权限.限制访问频率) django_rest_framework doc django_redis cache doc
- android sdk content loader 0%不动
Make sure that eclipse is not active. If it is active kill eclipse from the processes tab of the tas ...