Java 中,所有的对象都默认继承 Object,里面有几个默认的方法可以供我们重写,常见的有 equals()、hashCode()、toString() 等方法;在 Kotlin 中,所有的对象默认继承 Any,
public open class Any {
public open operator fun equals(other: Any?): Boolean
public open fun hashCode(): Int
public open fun toString(): String
}
它里面有三个方法可以供我们重写。Java 中的类,默认是可以继承的,而 Kotlin 中默认则是不能继承的,注意 open 这个关键字,有它修饰才可以继承,不管是类还是方法,或是属性值。
open class A {
open fun a () { print("A") }
}
class B : A(){
override fun a() {
print("B")
}
}
这里,继承使用 : 来表示,单独看这个看不出什么名堂,现在稍作调整
open class A1(name: String) {
var name = name
open fun a () { print("A") }
constructor() : this("a1")
}
class B1 : A1{
constructor() : super("b1")
override fun a() {
print("B1")
}
}
在这个例子中,A1 的构造方法为包含一个参数的构造,这点写法和 Java 中不一样,并且直接在 class 后面添加括号的构造方法为主构造,如果没参数,可以写个空括号,或者省略括号,这样就默认为无参构造。A1 中的 constructor() 为辅助构造方法,它必须调用主构造方法,就如上面写的一样。B1 中继承了 A1,此时柱构造后面跟的是 A1 的空构造,子类必须在构造方法中调用父类的主构造方法,因此,在 B1 的里面就有了 constructor() : super("b1") ,上述可以简化为
class B2 : A1("b2"){
override fun a() {
print("B2")
}
}
直接在 B2 的主构造后面跟随 A1 的主构造方法,我们再看看下面的一种情况
class B3 : A1{
constructor(name: String) : super(name)
constructor(name: String, age : Int) : this(name)
override fun a() {
print("B3")
}
}
B3 中,内部的辅助构造方法,最终必须调用到父类的主构造方法,就如 B3 中的两个参数构造方法调用了一个参数的构造,一个参数的构造调用了父类的一个参数的构造方法。再比如一个实体类继承了一个抽象类和一个接口,抽象类和接口恰好有相同的抽象方法,在 java 中,子类只能重写一个,但在 kotlin 中,重写后还是可以调用父类的方法
open class AA {
open fun ss () { println("A") }
fun a() { println("a") }
}
interface BB {
fun ss() { println("B") }
fun b() { println("b") }
}
class CC : AA(), BB{
override fun ss() {
super<AA>.ss()//调用 AA.ss()
super<BB>.ss()//调用 BB.ss()
}
}
fun test(){
val c = CC()
c.ss()
}
运行后,打印的值为
A
B
在java的 jdk 1.8 中,接口还是只能定义抽象方法和变量,不能定义可以重写的非抽象方法,但在 kotlin 中,不能定义常量,可以定义抽象和非抽象方法,举个例子
interface A {
var name:String //name 属性, 抽象的
fun start() { println("start A") } // 已实现
fun end() // 未实现
}
interface B {
fun start() { println("start B") } // 已实现
fun end() { println("end B") } // 已实现
}
class C : A {
override var name: String = "C" //重写属性
override fun end() { println("end C") } // 重写
}
class D : A, B {
override var name: String = "D" //重写属性
override fun start() {
super<A>.start()
super<B>.start()
}
override fun end() {
super<B>.end()
println(name)
}
}
fun test1(){
val d = D()
d.start()
d.end()
}
打印结构为
start A
start B
end B
D
Kotlin 比着 Java 多了一个扩展函数的概念,什么意思呢?看个例子
class A{
fun test(){
println(" test A ")
}
}
fun A.too(){
println(" too A ")
}
fun function(){
var a = A()
a.test()
a.too()
}
在这个例子中,定义了对象 A,A 中有个 test() 方法;上面的 A.too() 就是扩展的方法,它是个静态方法,优先于对象的存在;我们调用 function() 方法,打印数据如下
test A
too A
扩展的是静态的方法,但如果我们想直接调用,如下
class AA{
fun test(){
println(" test AA ")
}
companion object
}
fun AA.too(){
println(" too AA ")
}
fun AA.Companion.to(){
println(" to AA ")
}
fun function(){
var aa = AA()
aa.test()
aa.too()
AA.to()
}
调用 function() 方法,打印数据为
test AA
too AA
to AA