Kotlin学习教程(六)

简介: 《Kotlin学习教程(六)》介绍了Kotlin中的注解、反射、扩展函数及属性等内容。注解用于添加元数据,反射支持运行时自省,扩展则允许为现有类添加新功能,无需修改原类。本文还详细解释了静态扩展的使用方法,展示了如何通过companion object定义静态部分,并对其进行扩展。

Kotlin学习教程(六)

参考往期教程:
Kotlin学习教程(一)
Kotlin学习教程(二)
Kotlin学习教程(三)
Kotlin学习教程(四)
Kotlin学习教程(五)
Kotlin学习教程(六)
Kotlin学习教程(七)
Kotlin学习教程(八)
Kotlin学习教程(九)
Kotlin学习教程(十)

===

注解
注解是将元数据附加到代码的方法。要声明注解,请将annotation修饰符放在类的前面:

annotation class Fancy
注解的附加属性可以通过用元注解标注注解类来指定:

@Target指定可以用该注解标注的元素的可能的类型(类、函数、属性、表达式等)
@Retention指定该注解是否存储在编译后的class文件中,以及它在运行时能否通过反射可见(默认都是true)
@Repeatable允许在单个元素上多次使用相同的该注解
@MustBeDocumented指定该注解是公有API的一部分,并且应该包含在生成的API文档中显示的类或方法的签名中
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION,
AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
annotation class Fancy
用法
@Fancy class Foo {
@Fancy fun baz(@Fancy foo: Int): Int {
return (@Fancy 1)
}
}
如果需要对类的主构造函数进行标注,则需要在构造函数声明中添加constructor关键字,并将注解添加到其前面:

class Foo @Inject constructor(dependency: MyDependency) {
// ……
}
反射
反射是这样的一组语言和库功能,它允许在运行时自省你的程序的结构。
Kotlin让语言中的函数和属性做为一等公民、并对其自省(即在运行时获悉一个名称或者一个属性或函数的类型)与简单地使用函数式或响应式风格紧密相关。

在Java平台上,使用反射功能所需的运行时组件作为单独的JAR文件(kotlin-reflect.jar)分发。这样做是为了减少不使用反射功能的应用程序所需的
运行时库的大小。如果你需要使用反射,请确保该.jar文件添加到项目的classpath中。

类引用
最基本的反射功能是获取Kotlin类的运行时引用。要获取对静态已知的Kotlin类的引用,可以使用类字面值语法:

val c = MyClass::class
该引用是KClass类型的值。
通过使用对象作为接收者,可以用相同的::class语法获取指定对象的类的引用:

val widget: Widget = ……
assert(widget is GoodWidget) { "Bad widget: ${widget::class.qualifiedName}" }
当我们有一个命名函数声明如下:

fun isOdd(x: Int) = x % 2 != 0
我们可以很容易地直接调用它isOdd(5),但是我们也可以把它作为一个值传递。例如传给另一个函数。为此我们使用::操作符:

val numbers = listOf(1, 2, 3)
println(numbers.filter(::isOdd)) // 输出 [1, 3]
扩展
扩展是kotlin中非常重要的一个特性,它能让我们对一些已有的类进行功能增加、简化,使他们更好的应对我们的需求。

// 对Context的扩展,增加了toast方法。为了更好的看到效果,我还加了一段log日志
fun Context.toast(msg : String){
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
Log.d("text", "Toast msg : $msg")
}

// Activity类,由于所有Activity都是Context的子类,所以可以直接使用扩展的toast方法
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
......
toast("hello, Extension")
}
}

// 输出
Toast msg : hello, Extension
按照通常的做法,会写一个ToastUtils工具类,或者在BaseActivity中实现toast。但是使用扩展函数就会简单很。
上面的例子就是在Context中添加新的方法,让我们以更简单的方式去显示toast,并且不用传入任何context参数,可以被任何Context或者
它的子类调用。我们可以在任何地方(例如一个工具类文件中)声明这个函数,然后在Activity中将它作为普通方法来直接调用。当然了Anko中已经包括了
自己的toast扩展函数。有关Anko后面会讲到。

Kotlin扩展函数允许我们在不改变已有类的情况下,为类添加新的函数。
扩展函数是指对类的方法进行扩展,写法和定义方法类似,但是要声明目标类,也就是对哪个类进行扩展,kotlin中称之为Top Level。
扩展函数表现得就像是属于这个类的一样,而且我们可以使用this关键字和调用所有public方法。
扩展函数可以在已有类中添加新的方法,不会对原类做修改,扩展函数定义形式:

fun receiverType.functionName(params){
body
}
receiverType:表示函数的接收者,也就是函数扩展的对象
functionName:扩展函数的名称
params:扩展函数的参数,可以为NULL
在上面我们举的扩展的例子就是扩展函数.其中Context就是目标类Top Level,我们把它放到方法名前,用点.表示从属关系。在方法体中用关键字
this对本体进行调用。和普通方法一样,如果有返回值,在方法后面跟上返回类型,我这里没有返回值,所以直接省略了。

扩展属性
扩展属性和扩展方法类似,是对目标类的属性进行扩展。扩展属性也会有set和get方法,并且要求实现这两个方法,不然会提示编译错误。
因为扩展并不是在目标类上增加了这个属性,所以目标类其实是不持有这个属性的,我们通过get和set对这个属性进行读写操作的时候也不能使用
field指代属性本体。可以使用this,依然表示的目标类。

// 扩展了一个属性paddingH
var View.panddingH : Int
get() = (paddingLeft + paddingRight) / 2
set(value) {
setPadding(value, paddingTop, value, paddingBottom)
}

// 设置值
text.panddingH = 100
给View扩展了一个属性paddingH,并给属性增加了set和get方法,然后可以在activity中通过textview调用。

静态扩展
kotlin中的静态用关键字companion表示,但是它不是修饰属性或方法,而是定义一个方法块,在方法块中的所有方法和属性都是静态的,
这样就将静态部分统一包装了起来。静态部分的访问和java一致,直接使用类名+静态属性/方法名调用。

// 定义静态部分
class Extension {
companion object part{
var name = "Extension"
}
}

// 通过类名+属性名直接调用
toast("hello, ${Extension.name}")

// 输出
Toast msg : hello, Extension
上面例子中,companion object一起是修饰关键字,part是方法块的名称。其中方法块名称part可以省略,如果省略的话,默认缺省名为
Companion

静态的扩展和普通的扩展类似,但是在目标类要加上静态方法块的名称,所以如果我们要对一个静态部分扩展,就要先知道静态方法块的名称才行。

class Extension {
companion object part{
var name = "Extension"
}
}

// part为静态方法块名称
fun Extension.part.upCase() : String{
return name.toUpperCase()
}

// 调用一下
toast("hello, ${Extension.name}")
toast("hello, ${Extension.upCase()}")

//输出
Toast msg : hello, Extension
Toast msg : hello, EXTENSION

相关文章
|
22天前
|
算法 Kotlin
Kotlin教程笔记(24) -尾递归优化
Kotlin教程笔记(24) -尾递归优化
40 7
Kotlin教程笔记(24) -尾递归优化
|
23天前
|
Java Kotlin
​ Kotlin教程笔记(15) - 方法重载与默认参数
​ Kotlin教程笔记(15) - 方法重载与默认参数
28 4
​ Kotlin教程笔记(15) - 方法重载与默认参数
|
22天前
|
Kotlin
Kotlin教程笔记(20) - 枚举与密封类
Kotlin教程笔记(20) - 枚举与密封类
37 8
|
22天前
|
安全 Java 编译器
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
|
22天前
|
Java 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
|
22天前
|
安全 Kotlin
Kotlin教程笔记(23) -作用域函数
Kotlin教程笔记(23) -作用域函数
62 6
|
22天前
|
Kotlin
Kotlin教程笔记(21) -高阶函数与函数引用
Kotlin教程笔记(21) -高阶函数与函数引用
30 6
|
22天前
|
缓存 Kotlin Python
Kotlin教程笔记(25) -函数式编程
Kotlin教程笔记(25) -函数式编程
|
21天前
|
设计模式 Java Kotlin
Kotlin教程笔记(56) - 改良设计模式 - 装饰者模式
Kotlin教程笔记(56) - 改良设计模式 - 装饰者模式
36 2
|
21天前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
21 2