Kotlin作用域函数引发的遮蔽问题

server/2024/10/19 19:43:49/

前面讲了kotlinit变量引起的遮蔽问题,见Kotlin it隐式变量的遮蔽问题,本篇聊聊作用域函数(scoped function)可能引起的遮蔽问题。

先来看一个简单的示例:

kotlin">fun test(): String {val s: String = "asdf".also {println(it.length)}return s
}

这里涉及3个上下文:全局上下文、test函数局部上下文、also引入的上下文。

然后第2个示例:

kotlin">fun test(): String {val s: String = "asdf".apply {println(length)}return s
}

不过这里涉及4个上下文:全局上下文、test函数局部上下文、apply引入的大括号之间的上下文,以及调用apply的字符串对象的对象上下文。

两段程序极为相似,在词法和语法结构上光靠肉眼难以发现差异,但上下文环境却有着较大的差别。在我第一次学习到Kotlin的这个特性时,心里有些不安。

传统的函数式语言中,如Lisp,在使用类似Lambda表达式之类的匿名函数时会引入新的上下文,Java也同理,但不会引入新的对象上下文(Java要同时引入新的函数和对象上下文需要用匿名内部类)。而局部匿名函数在Kotlin中也会引入这个新的函数上下文,却可能引入一个隐式的对象上下文。而这个对象上下文能否观察到、是否醒目就取决于编辑器的提示了。

Kotlin中这样的设计可以让代码变得简洁,但有点过于简洁了,省略了一些有助于阅读的信息,在发生遮蔽的时候有些代码可能反而没有那么直观,比如:

kotlin">fun test(): String {val length = 1val s: String = "asdf".apply {println(length) // length ?}return s
}

kotlin">class Test {val length = 1fun test(): String {val s: String = "asdf".apply {println(length) // length ?}return s}
}

大家可以看出println(length)中的length分别指向哪个对象吗?

所以,我认为作用域函数中引入对象的上下文,有利于简化代码的编写,但是因为其可能导致不易察觉的隐式遮蔽,所以对阅读可能造成影响。甚至,如果经常复制粘贴代码或编写长篇大段的代码,在功能迭代更新时可能因为没有注意到遮蔽的发生而导致bug。

一点点建议

  1. 在使用作用域函数(scoped function)时尽量避免多层嵌套,尤其是多个作用域函数嵌套。(一种较为消极且安全的方式)
  2. 在引入对象上下文的作用域函数(例如apply)中使用this来引用对象的成员,来减少遮蔽想象的发生,方便阅读,例如:
kotlin">fun test(): String {val length = 1val s: String = "asdf".apply {println(this.length)}return s
}
  1. 避免不同上下文中同名变量的使用。(包括开发者定义的变量和隐式的it
  2. 标准库中的能满足或普通函数就能满足,尽量避免自定义一些作用域函数
  3. 团队中如果不可避免地自定义/扩展了作用域函数,就保持api的稳定,并完善相关文档说明和规范(比如,“新的自定义作用域函数禁止引入对象上下文”或对名称进行规范)

http://www.ppmy.cn/server/23948.html

相关文章

算法人生(12):从“优先级队列算法”到“”六点优先工作法”

算法思想和生活中很多解决问题的思想有着异曲同工之妙,让我们来看下今天的“优先级队列算法”可以怎么应用到我们的生活中吧! 优先级队列算法(Priority Queue Algorithm) 是一种特殊的数据结构,它在常规队列秉持着“先…

Linux的DNS域名解析服务

目录 1.DNS 1.1定义 1.2作用/功能 1.3域名结构 1.4两种查询方式 1.5DNS域名解析工作原理 1.6DNS系统类型 2.正向解析实验​ 2.1安装bind服务,查看配置文件 2.2配置文件配置及文件内容说明 3.反向解析实验 4.配置主从DNS服务器 1.DNS 1.1定义 DNS域名系…

特斯拉携手百度攻克在华推广辅助驾驶难题,马斯克意外访华成果显著

特斯拉近日宣布与科技巨头百度达成合作协议,共同为中国市场提供地图和导航服务,以进一步推动其辅助驾驶系统的广泛应用。这一重要进展得益于特斯拉CEO埃隆马斯克上周的意外访问。 更多消息:AI人工智能行业动态,aigc应用领域资讯 …

html+css+js+jquery实现在网页端将手动输入用户的信息转化成表格

1.实现的效果图 2.css代码 ​<style>*{background-color: antiquewhite;}#ss{font-size:20px;text-align: center;}#inputForm { margin-bottom: 20px; } #userTable { width: 100%; border-collapse: collapse; } #userTable th, #userTable td { border: 1px …

Android使用AlertDialog实现弹出菜单

最近又开始捣鼓APP&#xff0c;许多api , class都忘记怎么用了&#xff0c;楼下使用AlertDialog实现个弹出菜单&#xff0c;结果直接crash&#xff0c;查了半天&#xff0c;终于即将&#xff0c;记录一下…… 1 实现代码 AlertDialog.Builder mBuilder new AlertDialog.Builde…

机器学习-什么是 k-means?

1、什么是 k-means&#xff1f; k-means是一种无监督的分类学习算法。它的基本原理是以距离作为相似度的评价指标&#xff0c;用样本点到类别中心的误差平方和作为聚类好坏的评价指标&#xff0c;通过迭代的方法使总体分类的误差评分和函数达到最小的聚类方法。 2、 k-means聚…

Matlab 使用subplot绘制多个子图,一元拟合

实现效果&#xff1a; clc; clear;filename sri.xlsx; % 确认文件路径data readtable(filename); datavalue data{:,2:end}; datavalue datavalue;fig figure(Position, [0, 0, 1500, 900]); indexString ["(a)","(b)","(c)","(d)&qu…

解决:pip is configured with locations that require TLS/SSL

在使用pip进行软件包安装的时候出现问题&#xff1a; WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available. 解决方法&#xff1a; mkdir -p ~/.pip vim ~/.pip/pip.conf然后输入内容&#xff1a; [global…