美文网首页kotlin
10. 类和对象

10. 类和对象

作者: 厚土火焱 | 来源:发表于2017-11-06 00:48 被阅读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)

    • classModifier: 类属性修饰符,标示类本身特性。
    abstract 抽象类
    final 类不可继承,默认属性
    enum 枚举类
    open 类可继承,非默认属性,需要注意
    annotation 注解类
    • accessModifier: 访问权限修饰符
    private 定义的内部可见
    protected 同一个文件中或子类可见
    public 所有调用的地方都可见
    internal 同一个模块中可见

    相关文章

      网友评论

        本文标题:10. 类和对象

        本文链接:https://www.haomeiwen.com/subject/aakzpxtx.html