类的特点
- 所有字段必须有一个初始值,除非被lateinit 修饰表示为延迟初始化
构造函数
主构造器
主构造器中不能包含任何代码,初始化代码可以放在初始化代码段中,初始化代码段使用 init 关键字作为前缀。
次构造器
使用次级构造器需要直接或间接的关联到主构造器,次级构造器的代码执行之前,会先执行关联的初始化方法
/// 可把field的定义方法主构造方法中
/// 若无其他修饰符,主构造方法的constructor可省略
class Runnoob(var a: String){
var name:String = "name"
var url:String = "url"
var city: String = "city"
init {
println("init~~~~~~")
}
constructor (a:String, age:Int) :this(a){
city = "cccc"
println("我是次级构造器")
}
/// 可指定属性的默认值
constructor (a:String, age:Int, sex: Int=1) :this(a, age){
city = "xxxx"
println("我是次次级构造器")
}
}
getter and setter
filed关键字
在kotlin中,调用引用与赋值引用都是使用的get or set方法,因此我们不能再set 与 get里再对原先的引用进行任何操作,这样或导致无限递归从而堆栈溢出。
code
var city: String = "city"
get() = field.toUpperCase()
set(value) {
field = value
}
伴生对象
有的时候我们需要调用类的方法或者属性,在Java中,我们可以使用static静态变量解决这个问题,而在kotlin中没有这个关键字,我们需要使用 companion object 伴生对象。
class man {
companion object p {
fun speak() {
print("hello world")
}
}
}
fun main() {
man.p.speak()
}
值得注意的是,object并不是等效于java中的static,实际上他是一种单例对象
覆盖
在kotlin中,默认情况下方法,类都是是final的,也就是不可覆盖的,如果我们需要覆盖方法,那么需要
1.将类open修饰
2.将对应方法open修饰
open class person{
private var name = "xpf"
open fun speak(){
print(" i am person")
}
}
class man : person{
constructor() : super()
override fun speak() {
print(" i am man")
}
}
抽象类
kotlin中的抽象类与Java的类似。
abstract class person{
private var name = "xpf"
abstract fun speak() ;
}
class man : person{
constructor() : super()
override fun speak() {
print(" i am man")
}
}
嵌套类
类可以嵌套在其他类中,他们除了长在一个class内,并没有其他关系了,内部类与外部类并不会相互持有引用:
class Outer {
private val bar: Int = 1
class Nested {
fun foo() = 2
}
}
val demo = Outer.Nested().foo()
内部类
标记为 inner 的嵌套类能够访问其外部类的成员。内部类会带有一个对外部类的对象的引用:
class Outer {
private val bar: Int = 1
inner class Inner {
fun foo() = bar
}
}
val demo = Outer().Inner().foo() // == 1
匿名内部类
window.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) { …… }
override fun mouseEntered(e: MouseEvent) { …… }
})
数据类
据说这是kotlin的有一大亮点,可以理解为缩写的Java bean,只是很多方法以默认的形式被重写了。如equals
编译器自动从主构造函数中声明的所有属性导出以下成员:
equals()/hashCode() 对;
toString() 格式是 "User(name=John, age=42)";
componentN() 函数 按声明顺序对应于所有属性;(用于解构赋值)
copy() 函数(复制一个仅仅修改看一部分的对象)。
接口
kotlin中的接口与Java中的接口有比较大的不同
- 你可以在接口中定义属性。在接口中声明的属性要么是抽象的,要么提供访问器的实现。在接口中声明的属性不能有幕后字段(backing field),因此接口中声明的访问器不能引用它们。而在Java中,接口的数据始终被 public static final修饰
2.kotlin中接口的方法可以有实现也可以为抽象。因此这样实际上接口的实现就有多继承内味了,因此我们需要解决覆盖冲突,因此我们需要手动解决冲突
interface a {
fun speak() {
}
}
interface b {
fun speak() {
}
}
interface c:a,b {
override fun speak() {
super<a>.speak()
}
}