Kotlin中变量延迟初始化写法、定义常量的方式以及扩展函数的写法
内容来自于学习《第一行代码(第三版)》
对变量的延迟初始化
在实际开发过程中,一个类中如果存在很多的全局变量,为了保证它们能够满足Kotlin的空指针检查的语法标准,不得不做许多非空判断保护才行,如下:
class MainActivity:AppCompatActivity(){
private var adapter:MsgAdapter?=null
override fun onCreate(savedInstanceState:Bundle?){
...
adapter=MsgAdapter(msgList)
...
}
override fun onClick(v:View?){
...
adapter?.notifyItemInserted
}
}
而当代码中有了越来越多的全局变量实例时,这个问题就会变得越来越明显,到时候就会写大量额外的判空处理代码,只是为了满足kotlin编译器的要求,解决办法就是延迟初始化late init关键字,它可以告诉Kotlin编译器,我会在晚些时候对这个变量进行初始化,这样就不用在一开始的时候将它赋值为null了,代码优化如下:
class MainActivity:AppCompatActivity(){
private lateinit var adapter:MsgAdapter
override fun onCreate(savedInstanceState:Bundle?){
...
adapter=MsgAdapter(msgList)
...
}
override fun onClick(v:View?){
...
adapter.notifyItemInserted(msgList.size-1)
}
}
所以,当对一个全局变量使用了lateinit关键字时,一定要确保它在被任何地方调用之前已经完成了初始化工作,否则Kotlin将无法保证程序的安全性
另外,我们还可以通过代码来判断一个全局变量是否已经完成了初始化,这样在某些时候能够有效地避免对某一个变量进行初始化操作,优化代码如下:
class MainActivity:AppCompatActivity(){
private lateinit var adapter:MsgAdapter
override fun onCreate(savedInstanceState:Bundle?){
...
if(!::adapter.isInitialized){
adapter=MsgAdapter(msgList)
}
...
}
}
::adaper.isinitialized
用于判断变量是否已经初始化,如果没有则初始化
Kotlin中定义一个常量的方式
Kotlin中定义常量一般都是在companion、单例类或顶层作用域中使用const关键字声明一个变量,例如:
class test(){
companion object{
const val TAG="RightFragment"
}
}
扩展函数
扩展函数的意思是即使在不修改某个类的源码的情况下,仍然可以打开这个类,向该类添加新的函数
例如我现在需要实现一个统计一段字符串中字母的数量的功能,一般的常规写法是
object StringUtil{
fun lettersCount(str:String):Int{
var count=0
for (char in str){
if (char.isLetter()) {
count++
}
}
return count
}
}
然后调用该方法
val str="ABC123xyz!@#"
val count=StringUtil.lettersCount(str)
现在需要将这个函数添加到String类当中,首先编写一个String.kt文件。文件名虽然没有要求,但是为了便于查找最好是向哪个类中添加扩展函数就定义相同的Kotlin文件。当然,扩展函数也可以定义在任何一个现有的类中,不一定非要创建新文件。不过通常来说,最好将它定义成顶层方法,这样可以让扩展函数拥有全局的访问域。然后在String.kt文件中编写如下代码:
fun String.lettersCount():Int{
var count=0
for (char in this){
if (char.isLetter()){
count++
}
}
return count
}
注意:扩展函数的语法格式如下
fun ClassName.methodName(param1:Int,param2:Int):Int{
return 0
}
调用该扩展函数
val str="ABC123xyz!@#"
val count=str.lettersCount()