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

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

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

定义空类:

class Empty

含有成员函数的类:

fun main(args: Array) {
    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 [:][=]
[]
[]

如果属性类型可以从初始化语句中推断出来,那么类型就可以省略;
在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){
    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) {
    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) {
    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基础---类和对象)