6.类对象函数接口
kotlin都有超类Any,提供equals()、toString()、hsshCode()
6.1 继承
Kotlin 中所有的类都有共同的父类 Any [java object]
类的get/set
get() = this.toString()
set(value) {
field = value
}
class Example // 隐式继承于 Any
class Derived(p: Int) : Base(p)
默认类中所有的方法也是默认是final的,不能被继承,实现基类继承父类 重写…
//open 继承 , override重写覆盖同名方法需要open
open class Animal(food : String ){
open fun eat(food: String) {
}
}
class Dogl(food : String ) : Animall(food : String ){
override fun eat(food: String) {
//super调用父类的方法
super.eat(food)
}
}
抽象类 [abstract]
open class Base {
open fun f() {}
}
abstract class Derived : Base() {
override abstract fun f()
}
伴随对象[companion object 类似static]
class MyClass {
companion object Factory {
fun create(): MyClass = MyClass()
}
}
延迟属性lateinit[懒加载 在使用之前初始化]
那些被定义为拥有非空类型的属性,都需要在构造器中初始化.
但有时候这并没有那么方便.例如在单元测试中,属性应该通过依赖注入进行初始化, 或者通过一个 setup 方法进行初始化.在这种条件下,你不能在构造器中提供一个非空的初始化语句,但是你仍然希望在访问这个属性的时候,避免非空检查.
public class MyTest {
private var rocketDetailViewModel: RocketDetailViewModel?= null
lateinit var subject: TestSubject
@SetUp fun setup() {
subject = TestSubject()
}
@Test fun test() {
subject.method()
}
}
6.2接口
例子:
interface MyInterface{
var a:Int // abstract 接口中的属性要么是抽象的,要么提供访问器的实现
fun foo() {
}
fun setAge();
}
class MyFace : MyInterface {
override var a: Int = 0
get() = field
set(value) {
field = value
}
override fun setAge() {
TODO("Not yet implemented")
}
}
}
6.3 可见性修饰词[低->高]
Kotlin 中有四种修饰词:private,protected,internal,public
java类成员的访问控制权限:private、default、protected、public
局部变量,函数和类是不允许使用修饰词的
构造函数 constructor
: class C private constructor(a: Int) { ... }
6.4函数[亮点]
Kotlin 可以对一个类的属性和方法进行扩展,且不需要继承或使用 Decorator 装饰模式。
扩展是一种静态行为,对被扩展的类代码本身不会造成任何影响
扩展函数
扩展函数可以在已有类中添加新的方法,不会对原类做修改,扩展函数定义形式
添加一个 swap 函数
fun MutableList<Int>.swap(x: Int, y: Int) {
val temp = this[x] // this 对应 list
this[x] = this[y]
this[y] = tmp
}
属性扩展
val <T> List<T>.lastIndex: Int
get() = size-1
⚠️分析: 在不破坏原有类的情况拓展方法, java对拓展开放原则是大部分实现、继承、或者util直接换地方,那要是给String添加新方法呢?
kotlin提供类+拓展 这样等于类上新增,类.下就可以关联上了,
6.5泛型
class Box<T>(t: T){
var value = t
}
6.6枚举类
enum class Direction {
NORTH,SOUTH,WEST
}
6.7对象表达式和声明
如果父类有构造函数,则必须传递相应的构造参数。多个父类可以用逗号隔开,跟在冒号后面:
open class A(x: Int) {
public open val y: Int = x
}
interface B { ... }
val ab = object : A(1), B {
override val y = 14
}
6.8代理
类代理
interface Base {
fun print()
}
class BaseImpl(val x: Int) : Base {
override fun print() { printz(x) }
}
class Derived(b: Base) : Base by b
fun main() {
val b = BaseImpl(10)
Derived(b).print()
}
在 Derived 的父类列表中的 by 从句会将 b 存储在 Derived 内部对象,并且编译器会生成 Base 的所有方法并转给 b。
延迟
Delegate.lazy() 是一个接受 lamdba 并返回一个实现延迟属性的代理:第一次调用 get() 执行 lamdba 并传递 lazy() 并记下结果,随后调用 get() 并简单返回之前记下的值。
import kotlin.properties.Delegates
val lazy: String by Delegates.lazy {
println("computed!")
"Hello"
}
fun main(args: Array<String>) {
println(lazy)
println(lazy)
}
如果你想要线程安全,使用 blockingLazy(): 它还是按照同样的方式工作,但保证了它的值只会在一个线程中计算,并且所有的线程都获取的同一个值
观察者
Delegates.observable() 需要俩个参数:一个初始值和一个修改者的 handler 。每次我们分配属性时都会调用handler (在分配前执行)。它有三个参数:一个分配的属性,旧值,新值:
class User {
var name: String by Delegates.observable("<no name>") {
d.old,new -> println("$old -> $new")
}
}
fun main(args: Array<String>) {
val user = User() //kotlin 没new 省略
user.name = "first"
user.name = "second"
}
kotlin 类对象函数接口基础
最新推荐文章于 2024-05-29 20:02:07 发布