kotlin接口
开头我们介绍下kotlin的接口,kotlin接口跟java的接口差不多,jdk8中接口增加了默认方法实现,是为了兼容jdk向下兼容,还有考虑stream少写了很多代码,在kotlin中是否也可以写具体的方法,答案是肯定的。在多实现继承中有这样的问题,接口A有method方法的实现,父类B也有method方法实现,子类C怎么办,子类C**必须override相同的方法签名**,还有一个问题,怎样在子类C中指定调用A的实现,还有B的实现,这里kotlin也考虑的十分充分��
interface A {
fun method() {
println("A")
}
}
open class B{
open fun method(){
println("B")
}
}
/**
* 接口,父类中都有方法实现,子类必须自己实现一套
*/
class C: A, B(){
override fun method() {
//语法太风骚
super<A>.method()
super<B>.method()
println("C")
}
}
fun main(args: Array<String>) {
var c = C()
c.method()
}
kotlin抽象类
kotlin抽象类没什么好说的,只有一点,父类BaseClass中有method方法实现,子类ChildClass可以把父类的实现变成抽象方法
//抽象类
open class BaseClass{
open fun method() {
}
}
/**
* 可以用abstract方法override父类
*/
abstract class ChildClass : BaseClass() {
override abstract fun method()
}
kotlin伴生对象(Companion)
伴生对象的概念是什么,可以用java语言方式理解,它是静态内部类,为什么要设计这样的伴生对象?
首先我们了解对象声明的概念,java中没有提供直接对象,但是js中提供了对象,面向对象是靠对象来实现的,即使ts语法糖里有class关键字,但是本质还是对象,对象就可以不用实例化,直接调用。
//object declaration,对象声明
object MyObject {
fun method() {
println("method")
}
}
fun main(args: Array<String>) {
MyObject.method()
}
下面来说明kotlin的伴生对象,下面的例子就是伴生对象的使用例子
class MyTest {
companion object MyObject{
var a: Int = 100
// @JvmStatic
fun method() {
println("method invoked!")
}
}
}
fun main(args: Array<String>) {
MyTest.MyObject.method()
println("------")
println(MyTest.a)
MyTest.method() //类似于静态方法,Kotlin中没有静态方法
println("------")
val v = MyTest.MyObject
println(v.javaClass)
}
伴生对象是为了提供给kotlin像java一样,可以使用一个静态的使用方式,《effetive java》 中static是特别推荐用的,有很多好处,初始化的次数少,可以做缓存,推荐使用静态工厂方法来构造一个类的实例。
- ��kotlin中,与Java不同的是, 类是没有static方法的
- 在大多数情况下,kotlin推荐的做法是使用包级别的函数来作为静态方法,kotlin会将包级别的函数当做静态方法来看待
- 如果不提供伴生对象的名字,那么编译器会提供一个默认的名字Companion,MyObject描述可以省略
- ��虽然伴生对象的成员看起来像是Java中的静态成员,但在运行期,他们依旧是真实对象的实例成员(调用方式是kotlin的特定语法糖)
- 在jvm上,可以降版式对象的成员真正成为类的静态方法与属性,他们通过@JvmStatic注解来实现
- 伴生对象在编译后会生成一个静态的内部类
针对上面的tips,我们使用java反编译kotlin的class文件,开看一看伴生对象本质是什么
1.我们不使用@JvmStatic注解,执行javap MyTest.class
如上图看,根据我们调用方式虽然可以 使用MyTest.method(),但是MyTest反编译结果并没有method静态方法
2.我们加上@JvmStatic,然后重新build
如图就是对每条tips的最好的证明��