引言
在 Kotlin 中,我能够申明一般类、数据类、动态类,它也有抽象类和接口,其中 abstract 关键字只能作用在一般类。
类和对象
一般类
Kotlin 中的一般类通过 class 关键字定义,这品种默认都是 final 类型的,无奈被继承。如果心愿被继承,须要在后面减少 open 关键字
class Person(var id:Int?) { // id 可为 null
var name:String? = null
constructor():this(999) // 重载
cosntructor(id:Int, name:String):this(id) { // 重载
this.name = name
}
}
fun main() {var ps1= Person()
var ps2 = Person(20)
}
抽象类
通过 abstract class 定义一个抽象类,默认是 open class
abstract class BaseActivity {}\
接口
接口的定义和 java 十分相似
interface UserApi {}
动态类
object StudentManager{fun show() { // 留神,这是单例办法
// ..
}
@JvmStatic // 减少这个关键字才是 static 办法
fun show2(){// ..}
}
外部类
动态外部类
class A {
object Instance {var instance = A()
}
compannion object { // A 的静态方法
fun getInstance() : A = Instance.instance}
}
// A.getInstance()
一般外部类
class A {inner class Class2 {}
class Class3 {// 留神这个不是外部类}
}
扩大
class User(val name:String)
fun User.print() {print("用户名: $name")
}
fun main() {var user = User()
user.print()}
Kotlin 扩大能够在不批改原类的根底上减少性能,原类不受影响。没有真正减少代码,扩大的内容不参加多态,调用的哪个就是哪个。但如果子类的扩大笼罩了父类的扩大,如果用子类去调用该函数,会应用子类的扩大函数。总之,谁调用就应用谁的扩大。
属性也能够扩大,属性初始化只能通过 getter/setter 实现
当然也能够对伴生对象进行扩大,以实现动态化
委托
类委托
类委托和代理模式很相似,从 java 的角度看,就是类 A 实现一个公共接口或间接继承 B,而后外部持有一个 B 类对象。进而可在 A 类中应用 B 类的办法。
Kotlin 很容易实现上述形式
interface Base {fun print()
}
class BaseImpl(val x:Int): Base{override fun print() {println(x)
}
}
class Driver(b:Base) : Base by b
fun main() {var driver = BaseImpl(10)
Driver(driver).print()}
从上述代码能够看出,这里的 Driver 的 print 委托给 BaseImpl 实现
属性委托
val/var [属性名]:[类型] by [表达式]
其中表达式指的是委托代理类,该属性的 get 和 set 会交给该类的 getValue 和 setValue 实现。
class Example{var p : String by Delegate()
}
// 委托的类
class Delegate {operator fun getValue(thisRef: Any?, property: KProperty): String {return "$thisRef, 这里委托了 ${property.name} 属性"
}
operator fun setValue(thisRef: Any?, property: KProperty, value: String) {println("$thisRef 的 ${property.name} 属性赋值为 $value")
}
}
fun main(args: Array) {val e = Example()
println(e.p) // 拜访该属性,调用 getValue() 函数
e.p = "Runoob" // 调用 setValue() 函数
println(e.p)
}
输入后果为:
Example@433c675d, 这里委托了 p 属性
Example@433c675d 的 p 属性赋值为 Runoob
Example@433c675d, 这里委托了 p 属性
属性懒加载:
var lazyValue:String by lazy{// loading property}
该属性第一次用到时会调用 lazy{}代码块中的内容,并缓存到内存中,第二次就间接从内存中获取到值了。
属性记录器
class User{var name:String by Delegates.observable("初始值"){
prop, old, new ->
Log.d("old:$old, new:$new")
}
}
fun main(){val user = User()
user.name = "1"
user.name = "2"
}
当上述 main 开始执行时,输入:
old: 初始值,new:1
old:1,new:2
属性 Map 映射器
class Site(val map:Map){
val name:String by map
val url:String by map
}
fun main(){
var site = Site(mapOf(
"name" to "百度"
"url" to "http://www.baidu.com"
))
print(site.name) // 百度
print(site.url) // http://www.baidu.com
}
也就是说,咱们只需结构一个和 map 构造差不多的类,kotlin 就会主动帮忙解析,并将属性设置该该对象。
如果属性为 var,则须要把 Map 换成 MutabbleMap
class Site(val map:MutabbleMap){
val name:String by map
val url:String by map
}
fun main(){
var site = Site(mutableMapOf(
"name" to "百度"
"url" to "http://www.baidu.com"
))
print(site.name) // 百度
print(site.url) // http://www.baidu.com
}
函数类型委托
fun example(computeFoo: () -> Foo) {val memoizedFoo by lazy(computeFoo)
if (someCondition && memoizedFoo.isValid()) {memoizedFoo.doSomething()
}
}
其中 ()->Foo 是一个函数类型,也就是一个返回 Foo 的函数,相似于
interface A{void Foo();},相当于传了 new A。
而后 memoizedFoo 委托给 computeFoo 执行。
Kotlin 和 Java 互调
Kotlin 能够反对不写类间接写函数,而 Java 调用 Kotlin 这样的函数式,须要写文件名 Kt. 函数名即可。
Java 和 Kotlin 互调时,Kotlin 调用 java 代码,领有更多写法,反对闭包,lombda 等。
总结
本大节次要介绍了面向对象的基本知识和类委托、属性委托等