類的特點
- 所有字段必須有一個初始值,除非被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()
}
}