Kotlin基础(六)面向对象、类与接口等概念

132 阅读3分钟

构造方法

Kotlin中的类构造方法可以类似java中的编写:

class Rect{
    var h:Float;
    var w:Float;

    constructor(h: Float,w: Float) {
        this.h = h
        this.w = w
    }
}

上述定义了一个矩形类,里面有两个属性(长h、宽w)。constructor为其构造函数的声明关键字。这里要注意的是,在Kotlin中定义属性时需要给该属性赋初值,或者需要一个拥有该属性赋值的构造方法。 否则程序会出错。

也可以这样写:

class Rect(var h: Float,var w: Float){

}

这种写法可以既定义类的属性又声明了构造方法。 关于构造函数详细的写法可以参考:Kotlin中的构造函数


继承

Kotlin中的继承声明为 class 子类名:父类名{}

class Square : Rect(){

}

这里有一个父类Rect,一个子类Square。需要注意的是,父类需要声明open关键字,才可以被子类继承。

open class Rect{

}

在方法的重写上,子类需要声明override关键字来声明此方法为重写父类的方法。相应的父类也需要在对应的方法中声明open关键字

open class Rect{
    open fun S(){

    }
}

class Square : Rect(){
    override fun S(){

    }
}

抽象类

Kotlin的抽象类定义与java类似,接下来直接上代码:

abstract class Animal(var name: String){
    abstract fun type();
}

class Dog(name: String):Animal(name){
    override fun type() {
		
    }
}

使用abstract关键字声明Animal类为一个抽象类,内含一个type的抽象方法。Dog类在继承它的时候自动重写此type方法,并需要加上override的关键字。


接口定义与继承

Kotlin的接口定义和继承与java写法大致,以下是子类继承了父类和一个接口的例子:

abstract class Animal(var name: String){
    abstract fun type();
}

interface Ability{
    fun shout();
}

class Dog(name: String):Animal(name),Ability{
    override fun shout() {
        
    }

    override fun type() {

    }
}

is关键字

在java的多态中我们可以使用一个父类的对象通过instanceof关键字来判断其是否为某个子类的引用。而类似的在Kotlin里也可以使用is关键字来进行判断。

fun main(args: Array<String>) {
    var a: Animal = Dog("Boby");
    if(a is Dog){
        println(a.name);
    }
}

输出结果:

Boby

代理与委托

Kotlin可以使用by关键字实现代理模式,详情可见:kotlin 委托


单例

Kotlin可以利用object关键字声明一个类为单例模式。

object SignalInstance{

}

我们可以试着定义两个变量都为SignalInstance的。

var b = SignalInstance;
var c = SignalInstance;
println(b == c);

输出结果:

true

枚举型

Kotlin中通过enum class 关键字定义一个枚举型。如:

enum class NUMBER{
    ONE,TWO,THREE,FOUR,FIVE
}

通过类名.属性的格式可以获取该属性:

println(NUMBER.ONE);

输出结果:

ONE

可通过ordinal关键字获取此属性在枚举中的位置:

println(NUMBER.ONE.ordinal);

输出结果:

0

印章类

sealed关键字可以定义一个印章类,印章类让一个类拥有了有限多个子类。印章类甚至可以理解为一个特殊的枚举类。印章类本身不能被实例化。

sealed class Option(var num1:Int,var num2:Int){
    class add(num1: Int,num2: Int):Option(num1,num2){
        fun add() = num1+num2;
    }

    class sub(num1: Int,num2: Int):Option(num1,num2){
        fun sub() = num1-num2;
    }
}

在main函数中定义如下变量会出错:

 var x : Option = Option(1,1);

这是因为Option类为印章类,其本身不可被实例化。

以下是一段使用印章类的代码:

fun main(args: Array<String>) {
    var a : Option = Option.Add(2,3);
    var b : Option = Option.Sub(3,2);
    var list = listOf<Option>(a,b);
    for (o in list){
        if(o is Option.add){
           println(o.add());
        }else if(o is Option.sub){
            println(o.sub());
        }
    }
}

上述通过定义在Option的印章类中两个子类的对象,在通过调用其子类中的不通方法完成输出。 印章类可定义有限的子类,每个子类中都有其自定义的内容,这是与枚举相比的最大区别。