Kotiln類和繼承
類(class)
Kotlin中,使用class關鍵字生命一個類。類聲明由類名,類頭(指定其類型參數,主構造函數等)和大括號括起來的類體組成。
class MyClass public constructor(arg1:String){
}
構造器
Kotlin中,一個類可以有一個主構造函數或和一個或多個次構造函數。主構造函數是類頭的一部分,跟在類名(和可選的類型參數)後面,如果主構造函數沒有任何註解或可見性修飾符,可以省略constructor關鍵字。
主構造函數
主構造函數不包含任何的代碼,初始化代碼可以放到init關鍵字修飾的初始化塊中
主構造函數中的參數可以在初始化塊,或類體內聲明的屬性初始化器中使用
class MyClass (arg1:String){
var str:String=arg1
//初始化塊
init {
print(arg1)
}
}
第二構造函
類也可以聲明前綴有constructor的次構造函數,如果類有主構造函數,每個次構造函數都要委託給主構造函數,可以直接委託,也可以通過別的次構造函數間接委託。委託到同一個類中的另一個構造函數,用this關鍵字即可。
class MyClass (var arg1:String){
constructor():this("")//次構造函數
}
在主構造器中可以使用var和val,但是在第二構造函函數中不能使用var和val,這就意味着第二構造函數都是隻讀的,不能在構造器內部改變參數的值
默認參數
Java不支持默認參數,因爲JVM不支持,但是Kotlin函數支持默認參數,讓我們看一個簡單的例子
class MyClass (val bill:String = "Bill",var value : Float = 20.4F){
}
如果使用MyClass可以直接使用MyClass()。bill和value就會使用默認值
類成員
Kotlin中可以包含多種成員,如屬性、函數、嵌套類等
屬性的用法
1 . 屬性的基本用法
class MyClass{
var name:String = "a"
val value :Int = 20
}
2 . 屬性的getter和setter形式
// 屬性的get和set函數
class Customer
{
var mValue:Int =0
// 只讀屬性
val name:String
get() = "Bill"
var value:Int = 0
get()
{
println("value.get")
// return mValue
return field
}
set(value:Int)
{
println("value.set")
field = value
}
}
3 . field
Kotlin爲我們提供了更便捷的方式解決保存屬性值得問題,field。在屬性getter和setter中,可以將field當做成員變量使用,也就是通過field讀寫屬性值
函數
在Kotlin中函數既可以在類外部定義,也可以在類內部定義。如果是前者,是全局函數,如果是後者,是類成員函數。無論函數在哪定義,語法規則基本是一樣的。函數也支持默認參數值,帶默認參數的必須是最後幾個參數,也就是說如果某個參數帶默認值,那麼該參數後面所有的參數都必須有默認值
package testclass.testinterface
// 函數
// 全局函數(在類的外部定義)
// 類成員函數(在類的內部定義)
// 1. 參數的默認值
// 包含默認值的參數應該在最後
// 2. 命名參數
// 3. 可變參數,需要用vararg表示參數爲可變參數
// 4. 函數的單行表達式
// 5. 嵌套函數
class QACommunity1
{
// schema參數有默認值
fun printQACommunity(url:String, schema:String="https",value:Int = 0)
{
println("${schema}://${url}")
}
}
class Person1
{
fun process(value:Int, name:String = "Bill", age:Int = 30, salary:Float = 4000F)
{
println("value:${value}, name:${name}, age:${age}, salary:${salary}")
}
}
class Persons
{
// persons爲可變參數,課傳入任意多個Person1對象
fun addPersons(vararg persons:Person):List<Person>
{
val result = ArrayList<Person>()
for(person in persons)
{
result.add(person)
}
return result
}
}
fun getName():String = "Bill"
/*
fun getName():String
{
return "Bill"
}
*/
fun main(args: Array<String>)
{
QACommunity1().printQACommunity("geekori.com");
//Person1().process(30,"Bill", 30, 12000F)
// 命名參數
Person1().process(30,salary = 12000F,name = "Mary")
// 可變參數
var persons = Persons().addPersons(Person("Bill"), Person("Mike"), Person("John"))
for(person in persons)
{
println(person.name)
}
// 函數的單行表達式
println(getName())
// 嵌套函數
fun process(age:Int)
{
println("age:${age}")
fun process1()
{
}
}
process(40)
嵌套類
所謂嵌套類,就是類中定義的類
// 嵌套類
class Outer
{
private val bar:Int = 20
// 嵌套類
inner class Nested
{
fun foo() = bar
}
fun process()
{
println(Nested())
}
}
嵌套類可以使用inner聲明,這樣可以通過外部類(包含嵌套類的類)的實例引用嵌套類
修飾符(作用域)
- public:默認,總是可見
- internal:同模塊可見
- private:聲明範圍與同模塊的子作用域可見
- protected:類似於private,但對子類也可見
繼承
Kotlin中所有的類都有一個共同的超累類Any,對於沒有超類型聲明的類是默認超類。Any類不是java.lang.Object類,它只有equals,hashCode(),toString()3個成員方法。與Java不同,Kotlin通過“:”來繼承。
open class Parent
{
protected var mName:String = "Bill"
fun getName():String {
return mName
}
}
class Child : Parent()
{
fun printName()
{
println(getName())
}
}
要顯式聲明一個超類,可以把類型放到類頭的冒號之後,如果該基類有一個主構造函數,則其基類必須用主構造函數的參數就地初始化:
class B constructor(arg: String):A(arg){
}
- 在kotlin中,不僅類默認是不可繼承的,連方法默認也是不可重寫的。因此,如果要在子類中重寫方法,就需要在父類相應的方法前面加open關鍵字,而且要在子類重寫的方法前面加override關鍵字。
- 在kotlin中,val屬性可以被重寫爲var屬性,但反過來不可以
open class Parent
{
protected var mName:String = "Bill"
open fun function()
{
}
open val name:String = "Mary"
get()
{
println("獲取Parent.name屬性值")
return field
}
}
class Child : Parent()
{
fun printName()
{
println(mName)
}
override var name: String = "Mike"
get()
{
println("獲取Child.name屬性")
return field
}
set(value)
{
field = value
println("Child.name被寫入")
}
}
接口
- 在kotlin中接口與Java雷士,使用interface關鍵字聲明。一個類可以實現多個接口,實現的方法和類繼承相同。而且接口中的屬性和方法都是open的。
- 在kotlin中,允許接口的方法包含默認的方法體。對於有方法體的接口方法,並不要求一定重寫該方法。
// 對象和委託:對象表達式
// Kotlin中的對象是爲了代替Java中的匿名類
open class KotlinClass(name:String)
{
open var name = name
open fun verify()
{
println("verify")
}
}
interface MyInterface
{
fun closeData()
{
println("closeData")
}
}
fun process(obj:KotlinClass)
{
obj.verify()
if(obj is MyInterface)
{
obj.closeData()
}
}
fun main(args: Array<String>)
{
process(object :KotlinClass("John"),MyInterface{
override fun verify() {
println("object verify")
}
});
// 直接建立對象
fun foo()
{
val obj = object
{
var x:Int = 10
var y:Int = 20
}
println(obj.x + obj.y)
}
foo()
}