问题:

  • 在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的情况,真的特么太多了。
  • 所以做一层保护,就当是给自己心理安慰吧。

 评论