10.接口实现
java用extends继承类,implements实现接口,kt则统一使用:,中间用,分割;下面定义接口,ef:
interface Study{
fun readBooks()
fun doHomework()
}
Student实现Study接口,重写父类和实现接口方法都用override关键字,ef:
class Student(name:String, age:Int) : Person(name, age), Study{
override fun readBooks(){
println(name + " is reading.")
}
override fun doHomework(){
println(name + " is doing homework.")
}
}
11.多态编程的特性(和java一样)
下面为了体现写复杂点,首先创建一个Student类实例,定义了形参为Study接口的doStudy()方法;由于Student类实现了Study接口,因此Student的实例是可以传递给doStudy()的,接下来我们调用了Study接口的readBooks()和doHomework()方法,这个过程就叫作面向接口编程,也可称为多态,ef:
fun main(){
val student = Student("Jack", 19)
doStudy(student)
}
fun doStudy(study:Study){
study.readBooks()
study.doHomework()
}
kt中还增加了个额外的功能,允许接口中的定义函数默认实现(不过在java中sdk>1.8后也支持了),ef:
interface Study{
fun readBooks()
//若一个类进行该接口的实现,则readBooks强制实现,该类可选择性实现或不实现这个方法,默认不实现
fun doHomework(){
println("doHomework")
}
}
kt可见性修饰,对比java学习:
12.数据类,标准的数据类java中通常会重写equals()、hashcode()、toString(),但是kotlin只需要在需要的在该数据类前添加data关键字即可,ef:
//java的标准数据类
public class Cellphone(){
String brand;
double price;
public Cellphone(String brand, double price){
this.brand = brand;
this.price = price;
}
@Override
public boolean equals(Object obj){
if(obj instanceof Cellphone){
Cellphone other = (Cellphone) obj;
return other.brand.equals(brand) && other.price == price
}
return false
}
@Override
public int hashCode(){
return brand.hashCode() + (int) price;
}
@Override
public String toString(){
return "Cellphone(brand=" + brand + ", price=" + price + ")";
}
}
//kt则在数据类前添加data关键字得到同样的效果
data class Cellphone(val brand:String, val price:double)
//下面是测试验证该data
fun main(){
val cellphone1 = Cellphone("Samsung", 1299.99)
val cellphone2 = Cellphone("Samsung", 1299.99)
println(cellphone1)
println("cellphone1 equals cellphone2 " + (cellphone1 == cellphone2))
}
打印结果如下:
13.单例类,相对于java单例类的写法,kotlin更加简单,直接用object关键字修饰即可,ef:
//java中的单例类
public class Singleton{
private static Singleton instance;
private Singleton(){}
public synchronized static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
public void singletonTest(){
System.out.println("singleTest is called.")
}
}
//java调用则
Singleton singleton = Singleton.getInstance();
singleton.singletonTest();
//kotlin的单例类则很简单,在类前添加关键字object
object SingleTon{
fun singletonTest(){
println("singleTest is called.")
}
}
//kt若调用单例类中的方法也很简单,表面看上去相当于java的静态调用
//实质上kt已经创建了一个单例singleTon实例
SingleTon.singletonTest()
注意,object关键字也用作于匿名内部类的实现,ef:
//我们先来看一下java中的匿名内部类实现
new Thread(new Runnable(){
@Override
public void run(){
System.out.println("running")
}
}).start();
//下面我们看看kt object的匿名内部类
Thread(object : Runnable{
override fun run(){
println("running")
}
}).start())
//由于Thread类的构造符合java函数式API的使用条件,Runnable类中只有一个待实现方法,即使没有显示的重写run()kt也自动明白Runnable后的Lambda表达式是在run()中实现,所以可如下简化
Thread(Runnable{
println("running")
}).start()
//由于这个java方法中参数列表有且仅有一个java单抽象接口方法参数,可将接口名进行省略,简化后
Thread({ println("running") }).start()
//但上述还不是最简的,当方法的最后一个参数为Lambda时,可将Lambda的表达式移到方法括号的外面,且方法的唯一参数是Lambda时,括号可省略
Thread{ println("running") }.start()
//以上的Lambda使用会在之后提及