参考

        官网

class

class关键字定义一个类。

Any类,Any类中只有hashCode,toString以及equals三个方法。

        一个类由类名、类头以及类的主体——被大括号包裹起来的就是类的主体——三部分组成。其中类头,类主体是可选的。如果没有类主体,则大括号可以省略。如:

class Demo //定义一个类,没有类的主体,所以连大括号都可以省略

实例化

        跟java类型,只不过将new关键字给除掉。

构造函数

        分两种:primary constructor 和secondary constructors。primary只能有一个,而secondary可以有多个。

constructor,并且其可见性为public。

primary constructor与init代码块

constructor关键字定义。如果不需要改变构造函数的可见性,可以将constructor省略。

        2,它定义在类名或泛型(如果有泛型)之后。

        3,不能写任何代码

init代码块中进行。

        5,其参数只可以使用在init代码块以及类成员变量的初始化中。但可以通过var或val为类定义一个同名的变量。

        6,如果只使用默认的构造函数,则可以在类名或泛型(如果有泛型)之后加小括号,或者直接什么都不写;但如果添加了constructor关键字,则必须写小括号。

示例一,默认构造函数

class Demo1{//默认构造函数——什么都不写
	fun demo(){
		println(toString())
	}
}
class Demo2(){//默认构造函数——直接写一个小括号,可以在小括号中写参数列表
	fun demo(){
		println(toString())
	}
}

class Demo3 constructor(){//必须写小括号
	fun demo(){
		println(toString())
	}
}

//class Demo4 constructor{//不写小括号会编译失败
//	fun demo(){
//		println(toString())
//	}
//}

示例二,基本使用

class Demo<T> constructor(t : T){//通过constructor关键字指定primary构造函数

    init {
        t.toString()
    }
}

示例三,省略constructor以及不能省略constructor:

fun main(args:Array<String>){
	var d = Demo("----")//实例化对象
	var d2 = Demo2("----")//此编译时会报错,因为Demo2的构造函数是private,外界不能访问
}

class Demo (t : String){//省略constructor关键字

    init {
        t.toString()
    }
}
class Demo2 private constructor(t : String){//将构造函数指定为private,所以不能省略constructor关键字

    init {
        t.toString()
    }
}

示例四:init代码块:

fun main(args:Array<String>){
	var d = Demo("----")
}

class Demo (t : String){//省略constructor关键字

    init {
        println(t)//在init代码块中进行primary constructor的操作
    }
}

示例五:构造函数参数的使用范围

fun main(args:Array<String>){
	val a = Adapter(Demo())
}

class Demo{
	fun demo():String{
		return "this is from demo"
	}
}

class Adapter(ctx:Demo) {
     val inf = ctx.demo()//使用ctx进行初始化类的成员变量
	 init{
		println(ctx.toString())//ctx使用在init代码块中
	 }
	 fun test(){
		println(ctx.toString())//编译时会报unresolved reference: ctx——因为ctx是构造函数中参数,只能用在变量初始化或init代码块中
	 }
}

        如果将test()方法中的ctx改为inf,则可以编译通过也可运行。

示例六:定义与构造函数参数同名的变量

fun main(args:Array<String>){
	val a = Adapter(Demo())
	a.test()
}

class Demo(s:String="default"){
	fun demo():String{
		return "this is from demo"
	}
}

class Adapter(val ctx:Demo) {//添加一个val或var关键字,则该类会自动生成一个ctx成员变量,所以该类中的各个方法中均可使用该ctx
	 fun test(){
		println(ctx.toString())//可以使用ctx,因为Adapter类中有一个名为ctx的成员变量
	 }
}

        反编译Demo与Adapter对应的class文件,如下:

kotlin setBackgroundResource 变形_泛型

kotlin setBackgroundResource 变形_构造函数_02

        从中很容易看出变量名前添加var或val与不添加的区别。

Secondary Constructors

        1,可以有多个

constructor定义

this指代别的构造函数。

        4,无论定义多少个Secondary,primary一定存在。

示例一,通过this指定别的构造函数

fun main(args:Array<String>){
	Demo1("first2","22")
}

class Demo1{//默认无参的primary构造函数
	init{
		println("init 块")//最先执行
	}
	constructor(a:String){//其代理了primary,只不过primary是无参的
		println("one a=$a")//第二个执行
	}
	
	constructor(a:String,b:String):this(b){//代理一个参数的构造函数,并且将参数b传递到该构造函数中
		println("two a=$a,b=$b")//最后执行
	}
}

示例二,有参的primary

class Demo1(d:Int){
	init{
		println(d)
	}
	constructor(a:String):this(3){//必须通过this来代理primary,同时为其传递参数,这里直接传递具体参数值
		println("one a=$a")
	}
	
	constructor(a:String,b:String):this(b){//将参数b的值传到到构造函数中,并没有传递具体的参数值
		println("two a=$a,b=$b")
	}
}