Scala的隐式转换

最早写安卓的应该知道,每个点击事件就是一个匿名内部类,例如

1
2
3
4
5
6
7
loginBtn = (Button) findViewById(BTN_ID);
loginBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Login();
}
});

后来,有了注解的自动调用方式

1
2
3
4
@OnClick(BTN_ID)
public void onClickBtn(View view){
Login()
}

再后来,支持了Lambda表达式,更方便阅读了

1
loginBtn.setOnClickListener(view -> Login())

最近学了Scala,又发现了一种新的东西,有点像Lambda,但是又是一种新的思路
叫隐式转换

1
2
3
4
5
6
7
8
9
10
11
12
//首先定义好转换函数
implicit def viewToListener(f:(v View)=>Unit):View.OnClickListener={
new View.OnClickListener() {
@Override
public void onClick(View view) {
f(view);
}
}
}

// 调用处
loginBtn.setOnClickListener(_:View => Login())

是不是傻眼了,调用几乎跟Lambda处一样,却多定义了一个函数。
没错,这样看是傻了吧唧的,但是要知道这是Scala啊,不是Java。如果你没有现成的setOnClickListener方法调用,没有封装好的API,这玩意儿就出奇的有意思。
再举个例子

1
2
3
def plus(a:Int, b:Int)={
a + b
}

那调用的时候就是

1
plus(1,2)

如果你想让字符串”1” 和字符串”2”相加
那就的这样

1
2
3
4
5
6
val a = new StringOps("1").toInt();
val b = new StringOps("2").toInt();
plus(a,b)

//搞成一行就是
plus(new StringOps("1").toInt() ,new StringOps("2").toInt());

相当啰嗦
定义一个隐式函数做一个隐式转换

1
implicit def str2Int(x: String): Int = new StringOps(x).toInt()

使用

1
2
3
4
5
6
7
8
// 导入包隐式转换工具函数(包名根据实际情况有变化)
import com.xxxxUtil._

...

// 实际使用
plus(1,2)
plus("1","2")

如果你有IDEA,会显示成这样
不显示的话,参考链接里有调整方法

直接把String转换成了Int

当然,虽然方便了,缺点也很明显,

  1. 如果不开IDEA提示,你会看的很懵逼,甚至你会怀疑编译器坏了。
  2. 如果str2Int转换出异常了,报错的信息对初学者来说,又是一个懵逼的存在
  3. 如果存在另一个隐式转换,入参和出参一模一样。会报错

这下编译器真的懵了,不知道怎么转了

我目前就实验了这么一点点,后面有时间继续看看这里面还有啥好玩的

参考链接

调节IDEA显示隐式转换:https://blog.jetbrains.com/scala/2018/07/25/intellij-scala-plugin-2018-2-advanced-implicit-support-improved-patterns-autocompletion-semantic-highlighting-scalafmt-and-more/

工具书:《Scala编程 第三版》

喜欢请点个赞
转载请注明出处:https://xzing.github.io/
如有错误,请务必指正。谢谢
我的博客:https://xzing.github.io/