问题:
- 在Java层中,我的java类库有这个函数:
public static final String COMMON_TAG = "L_DEF";
public static void d(String tag, String message) {
if (tag == null || tag.length() <= 0) {
tag = COMMON_TAG;//log函数中,filter一下tag是否是一个空值或者空字符串,避免打一个空Tag
}
Log.d(tag, message);
}
- 我在kotlin中也想做一个类似的实现。
- 开始实现.
尝试翻译:
- 一开始我只是以为,kotlin的语法上有些变化,基本实现思路还是和java差不多的。于是哐哐开始敲:
private const val INNER_TAG = "L_DEF"
fun d(tag: String?, msg: String?) {
if(tag==null||tag.length<=0){
tag=INNER_TAG//这一行会报错!!!!!
}
Log.d(tag, TextUtil.filterNull(msg))
}
感兴趣的同学,可以把上述的代码拷到kotlin文件中,会发现各种报错…………
如上注释,报错的一行:
Val cannot be reassigned
WTF?这是什么神奇的操作?
kotlin语言中,函数的入参定义是val形式的?局部常量?不可变更?
函数入参val类型
- 是的没错,从上面得出的结论:
- kotlin的fun函数入参,都是val形式,也就是说不可以被重新赋值。
- 因此像上面的做法,是压根在kotlin上玩不转的。
- 网上查了下资料,发现其实在kotlin早期的设计里,是可以给fun函数的入参,定义var类型的。
- 但是后续在新的版本中删除了这个特性。
- 原因嘛,大家看下这个链接:
- 去除原因
- 主要描述基本就是:
- 这不是一种好的写法(……我默默地想回去把java的实现也改了)
- 大家默认以为这是引用传参,实际上kotlin不是引用传参的(惊奇,我又发现了新大陆)
- kotlin构造函数中,传参val、var其实是不一样的(这个我们后面可以单独聊聊)
- 简而言之,就是不支持这个特性。
新方案:
- 楼主是个java过来的强迫症患者,还是想要做下这个逻辑判断,而且,基于Kotlin,我们上面的这个log.d()函数,还有优化空间。
private const val INNER_TAG = "L_DEF"
private fun filterTag(tag: String? = INNER_TAG): String? {//定义一个入参的默认值
var tmp = tag
if (TextUtil.isEmpty(tmp)) {
tmp = INNER_TAG
}
return tmp
}
fun d(tag: String? = INNER_TAG, msg: String?) {
//定义一个入参的默认值(这样情况下,甚至可以让调用方忽略tag的传入,不要tag的时候更省事了)
val tmp = filterTag(tag)
Log.d(tmp, TextUtil.filterNull(msg))
}
- 如上述代码,我们首先针对kotlin的入参默认值特性,可以支持外部不传入tag入参,将使用我们定义的const常量做为tag
- 同时,定义一个函数局部变量tmp,用来做过滤,防止传null和传空字符串。
为啥过度封装?
- 也许有同学会问,kotlin的设计不就是???,然后各种?让你用?来防止null的情况吗
- 是的,kotlin的语言特性,很多地方真的不用再判空了。
- 但是很多时候,我们工程里还特么有java语言和kotlin的相互调用。
- 特么java给kotlin传null的情况,真的特么太多了。
- 所以做一层保护,就当是给自己心理安慰吧。