kotlin

10. 类和对象

2017-11-06  本文已影响128人  厚土火焱

类的属性可以使用 var 声明变量,可以使用 val 声明常量。
属性的引用可以用 (.)符号来实现。
属性取值和赋值的 getter 和 setter 都是可选的 。
val 不允许设置 setter 函数,它是只读的。

class Person{
    var lastName :String = "zhang"
    get() = field.toUpperCase()     //转换为大写
    set

    var no: Int = 100
    get
    set(value) {
        if (value < 10) {
            field = value
        }else{
            field = -1
        }
    }

    var height:Float = 145.4f
    private set

    fun addOne(x: Float) {
        height += x
    }
}

这个 Person 类的 height 把 setter 设置为私有的,外部不能直接修改,需要通过 Person 类提供的方法来修改。这里提供了 addOne 方法。

    var person :Person = Person()
    person.lastName = "wang"
    println("lastName is ${person.lastName}")

    person.no = 9
    println("no is ${person.no}")

    person.no = 20
    println("no is ${person.no}")

    println("height is ${person.height}")
    person.addOne(1f)
    println("height is ${person.height}")

在 main 里实现这些代码,对 Person 类做相应的访问。
运行结果

lastName is WANG
no is 9
no is -1
height is 145.4
height is 146.4
类的构造器

Kotlin 的类是通过 constructor 来实现构造器的。构造器有主构造器和次构造器之分。
主构造器中不能包含任何代码,初始化代码可以放在 init 初始化代码段中。

class Pp constructor(firstName: String){
    init {
        System.out.println("First name is $firstName.")
    }
}

这样在实例化的时候,会打印出一句话来

var p = Pp("Joel")
First name is Joel.

类的 constructor 关键字一般是可以省略的。如果主构造函数有注解或可见性修饰符,则 constructor 关键字不可省略,并且这些修饰符要放在 constructor 前面。
类也可以声明前缀有 constructor 的次构造函数。
当类有一个主构造函数,每个次构造函数需要委托给主构造函数,可以直接委托或通过别的次构造函数间接委托。委托到同一个类的另一个构造函数用 this 关键字。

class Person constructor(firstName: String){

    constructor(name: String, parent: Person): this(name){
        
    }
}

抽象类没有声明任何构造函数的,会有一个生成的不带参数的主构造函数。构造函数的默认可见性是 public 。如果不希望类有这个公有构造函数,则需要声明一个带有非默认可见性的空的主构造函数。

class DontCreateme private constructor(){

}

再看一个类的示例

package main

fun main(args: Array<String>) {
    val cofox = Cofox("金龙翼移动办公", 1000)
    println(cofox.Sitename)
    println(cofox.Url)
    println(cofox.Country)
    cofox.PrintTest()
}

class Cofox constructor(name: String){
    //  大括号内是类体构成
    var Url: String = "http://www.cofox.com"
    var Country: String = "CN"
    var Sitename = name

    init {
        println("初始化网站名称:$name")
    }

    //  次构造函数
    constructor(name: String, alexa: Int): this(name){
        println("Alexa 排名 $alexa")
    }

    fun PrintTest(): Unit {
        println("我是类的函数")
    }
}

运行结果

初始化网站名称:金龙翼移动办公
Alexa 排名 1000
金龙翼移动办公
http://www.cofox.com
CN
我是类的函数
继承类

Kotlin 默认类都是 final 的。如果类需要被其他类继承,那么要让这个类 open 才行。
当 fun 是 open 的时候,那么也是可以被 override 的。

open class Base{
    open fun f(){}
}

abstract class Derived :Base(){
    override abstract fun f()
}

由于 Base 类是 open 的,所以 Derived 可以继承 Base 。
由于 f() 是 open 的,所以可以被 override

嵌套类

类可以嵌套其他类
当要引用类内的函数时,类后需要跟括号

class Outer{
    private val bar : Int = 1
    class Nested{
        fun foo() = 2
        class Thrd{
            fun mee() = "meyaya"
        }
    }
}

在 main 函数中这样调用 Outer 里的类和函数

    val demo = Outer.Nested().foo()
    val demo2 = Outer.Nested.Thrd().mee()
    println(demo.toString() + ":" + demo2)

执行结果如下

2:meyaya
内部类

当把嵌套在内部的类标记为 inner 内部类时,每层的引用都需要加括号。
内部类可以访问外部类成员,也可以通过 this@外部类 ,从而达到能获取外部类实例的使用模式。

class Outer{
    private val bar : Int = 1
    inner class Nested{
        fun foo() = bar     //访问外部类成员
        inner class Thrd{
            fun mee() = "meyaya"
            fun innerTest(){
                var o = this@Outer
                println("这是获取外部类成员" + o.bar.toString())
//                bar
            }
        }
    }
}

在 main 中可以这样调用

    val demo = Outer().Nested().foo()
    val demo2 = Outer().Nested().Thrd().mee()
    println(demo.toString() + ":" + demo2)
    Outer().Nested().Thrd().innerTest()

运行结果

1:meyaya
这是获取外部类成员1

不仅如此,class 中的 o 可以像在 main 中一样调用 class 里的函数。

匿名内部类

使用对象表达式来创建匿名内部类
首先定义一个接口,接口内是一个 test() 函数

/*
* 定义接口
* */
interface TestInterFace{
    fun test()
}

创建一个 Test 类,类内有一个 成员 v 和一个函数,函数的参数为 TestInterFace 接口。

class Test{
    var v = "成员属性"
    fun setInterFace(test: TestInterFace){
        test.test()
    }
}

在主函数中,先声明实例化这个Test类。
试着打印一下这个类的成员 v,看是否能成功。

var test = Test()
println(test.v)

类实例 test 的 setInterFace 函数的参数是接口,这里用对象表达式来创建接口对象,即匿名内部类的实现。

    test.setInterFace(object: TestInterFace{
        override fun test() {
            println("对象表达式创建匿名内部类的实例")
        }
    })
类的修饰符

类的修饰符包括:类属性修饰符(classModifier)和 访问权限修饰符(accessModifier)

abstract 抽象类
final 类不可继承,默认属性
enum 枚举类
open 类可继承,非默认属性,需要注意
annotation 注解类
private 定义的内部可见
protected 同一个文件中或子类可见
public 所有调用的地方都可见
internal 同一个模块中可见
上一篇 下一篇

猜你喜欢

热点阅读