美文网首页
4、Kotlin基础---类和对象

4、Kotlin基础---类和对象

作者: SkyFireDragon | 来源:发表于2019-08-14 22:51 被阅读0次

    1、类定义
    Kotlin类可以包含:构造函数和初始化代码块、函数、属性、内部类、对象声明。
    创建类:

    class Runoob{       //创建名为Runoob的类
    }
    

    定义空类:

    class Empty
    

    含有成员函数的类:

    fun main(args: Array<String>) {
        var s = Student()
        s.introduce()
    }
    
    class Student{
        fun introduce(){ println("I am a student") }
    }
    

    类的属性
    类的属性可以用关键字var声明为可变的,否则使用只读关键字val声明为不可变。

    例子:
    class Student{
      var name:String = ...
      var address:String  =... 
      var phone:String  =...
    }
    

    kotlin中创建对象没有了new关键字,我们可以像调用普通函数一样调用类的构造方法;
    例如:

    val student = Student()
    

    想要使用类中的属性,只要用名称引用它即可
    例如:

    student.name
    

    getter和setter
    属性声明的完整语法:

    var <propertyName>[:<PropertyType>][=<property_initializer>]
    [<getter>]
    [<setter>]
    

    如果属性类型可以从初始化语句中推断出来,那么类型就可以省略;
    在kotlin中,声明一个类的成员变量时,默认实现了getter和setter方法;
    用val修饰的属性不允许设置setter函数,因为它本身就是只读的;

    例如:
    var allByDefault:Int?   //错误:需要一个初始化语句
    var initialized = 1     //类型为Int,默认实现了getter和setter
    val simple:Int?     //类型为Int,默认实现了getter,但必须在构造函数中初始化
    val inferredType = 1    //类型为Int,默认实现了getter
    

    在kotlin的getter方法中不能使用当前属性的引用,set方法中不能对当前属性进行赋值;

    例如:
    var no:Int = 100
    get() = no      //这里如果使用当前属性的引用,会递归调用属性的get方法
    set(value){
    no = value  //同理,如果在这给no赋值,会递归调用属性的set方法
    }
    

    为了防止这种情况的发生,kotlin引入了后端变量的概念,后端变量使用field表示;

    例如:
    class Student{
        var number:Int = 1001
        get() = getDate()+field
        set(value){
            field = getDate()+value
        }
    
        fun introduce(){ println("I am a student") }
         //获取年份
        private fun getDate():Int{
             var date = Calendar.getInstance().get(Calendar.YEAR)
             return date*10000
        }
    }
    

    非空属性必须在定义的时候初始化,kotlin提供了一种可延迟初始化的方案,使用lateinit关键字描述属性:

    public class MyTest{
      lateinit var subject:TestSubject
    
      fun setup(){
          subject = TestSubject()
      }
    }
    

    主构造器
    主构造器不能包含任何代码,初始化代码可以放在初始化代码段中,初始化代码段使用init关键字作为前缀。

    class Person constructor(firstName :String){
      init{
        println("FirstName is $firstName")
      }
    }
    

    当然在这里主构造器的参数可在初始化的代码片段中使用,也可以在属性初始化的代码中使用;另
    外一种简单的写法就是用主构造器来定义属性并初始化属性值。例如:

    class Person(val firstName:String,val lastName:String){
        //....
    }
    

    如果构造器有注解,或者有可见度修饰符,这时constructor关键字是必须的,注解和修饰符要放在它之前。

    次构造函数
    类也可以有二级构造函数,需要添加前缀 constructor

    class Person{
      constructor(parent:Person){
        parent.children.add(this)
      }
    }
    

    如果类有主构造函数,每个次构造函数都要,直接或间接通过另一个次构造函数代理主构造函数。在同一个类中代理另一个构造函数使用关键字this关键字:

    class Person(val name:String){
      constructor(name:String,age:Int):this(name){
          //初始化...
      }
    }
    

    如果一个非抽象类没有声明构造函数(主构造函数或次构造函数),它会会产生一个没有参数的构造
    函数,构造函数时public的,如果你不想你的类有公有的构造函数,你需要声明一个空的主构造函
    数:

     class Single private constructor(){}
    
    实例练习:
    class WebSite constructor(name:String){
        var url:String ="http://www.baidu.com"
        var country:String = "CN"
        var siteName = name
    
        init{
            println("初始化网站名:$name")
        }
    
        constructor(name:String,alexa:Int):this(name){
            println("Alexa 排名 $alexa")
        }
    
    }
    

    2、抽象类
    抽象类和java一样使用abstract修饰,同样使用abstract修饰的成员方法不存在具体实现。
    注意:无需对抽象类或抽象成员标注open注解。

    open class Base {
        open fun f(){}
    }
    
    abstract class Dervied:Base(){
        abstract override fun f()
    }
    

    嵌套类
    kotlin中可以嵌套的声明类,这里和java内部类不同,其他类要使用嵌套类时,只需要外部类的
    类名引用来创建嵌套类的对象,如下:

    class Outer{        //外部类
        private val bar:Int = 1
        class Nested{       //嵌套类
            var ot:Outer = Outer()
           fun foo() {
                println(out.bar)  //嵌套类想要引用外部类的变量,需要先创建外类的对象
            }
        }
    }
    
    fun main(args:Array<String>){
        val demo = Outer.Nested().foo()
        println(demo)
    }
    

    内部类
    内部类使用inner关键字来表示。
    内部类会带有一个对外部类的对象的引用,所以内部类可以访问外部类成员属性和成员函数。

    class Outer{
        private val bar:Int=1
        var v = "成员属性"
        inner class Inner{
            fun foo() = bar
            fun innerTest(){
                var o = this@Outer
                println("内部类可以引用外部类的成员,例如:"+o.v)
            }
      }
    }
    
    fun main(args: Array<String>) {
        val demo = Outer().Inner().foo()
        println(demo)
        val demo2 = Outer().Inner().innerTest()
        println(demo2)
    }
    
    匿名内部类
    class Demo{
        fun setInterface(test:TestInterface){
            test.test()
        }
    }
    
    interface TestInterface{
        fun test()
    }
    
    fun main(args: Array<String>) {
        var demo = Demo()
        demo.setInterface(object :TestInterface{
            override fun test() {
                println("匿名内部类的方法,哈哈哈")
            }
        })
    }
    

    这里匿名内部类和java中的有区别,object:TestInterFace中的object是kotlin的关键字;

    类的修饰符总结
    和java一样,类的修饰符分为两种classModifier和accessModifier:

    classModifier:类属性修饰符,用来标识类本身特性。
    abstract        //抽象类
    final           //类不可继承,默认属性
    enum        //枚举类
    open        //可继承类,类默认是final的
    annotation  //注解类
    
    accessModifier:访问权限修饰符
    

    private //仅在同一个文件中可见
    protected //同一个文件中或子类中可见
    public //所有调用的地方都可见
    internal //同一个模块中可见

    相关文章

      网友评论

          本文标题:4、Kotlin基础---类和对象

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