其他
- 其他
- 鏈接
鏈接
- 多重聲明
- Ranges
- 類型檢查和自動轉換
- This表達式
- 燈飾
- 運算符重載
- 空安全
- 異常
- 註解
- 反射
- 動態類型
多重聲明
- 多重聲明
- 例子:一個函數返回兩個值
- 例子:多重聲明和Map
多重聲明
有時候可以通過給對象插入多個成員函數做區別是很方便的,比如:
//多重聲明
data class Person(var name:String,var age:Int)
val (name,age)=Person("wyc",27)
println(name)
println("$age")
輸出
wyc
27
多重聲明在一次的活動創建了多個變量,兩個新變量name
和age
可以獨立使用
多重聲明被編譯成以下代碼:
val name=persion.component1()
val age=person.component2()
//下面是兩個方法在class中的顯示
operator fun component1(): Any {
return name
}
operator fun component2(): Any {
return age
}
多重聲明也可以在for循環中用
//多重聲明在for循環中的使用
fun getComponentTest(){
val collections= linkedMapOf("wyc" to 1,"xjy" to 2)
collections["lyb"]=3
collections["my"]=4
for ((a,b)in collections){
println("key is $a,value is $b")
}
}
輸出結果
key is wyc,value is 1
key is xjy,value is 2
key is lyb,value is 3
key is my,value is 4
參數a
和b
是component1()
和component2()
的值
一個函數返回兩個值
要在一個函數想返回兩個值:比如,一個對象結果,一個是排序的狀態。在kotlin中的一個緊湊的方案是聲明data類並返回實例:
//返回兩個值,根據數據類來返回,數據類自動聲明component函數
data class Result(val result:Int,val state: Person)
data class Person(var name:String,var age:Int)
fun function(result:Int, state: Person):Result{
return Result(result, state)
}
fun getDataTwoResult(){
val (result,status)= function(15, Person("wyc",27))
println("result is $result,status is $status")
}
輸出結果
result is 15,status is Person(name=wyc, age=27)
數據類自動聲明componentN()
函數
**注意:**也可以使用標準類Pair
並讓標準函數返回Pair
,但可讀性不強,是由於標準類中必須手動聲明component()
,並且標準類的toString()
沒有自動轉爲參數的toString,標準類和Java類是一樣的
多重聲明和Map
轉換map最好的辦法是下面這樣:
for((key,value)in map){}
爲了能實現這樣,我們需要:
通過提供
iterator()
函數序列化呈現map通過
component1()
和component1()
函數時把元素成對呈現
事實上,標準庫提供了這樣的擴展:
public inline operator fun <K, V> Map<out K, V>.iterator(): Iterator<Map.Entry<K, V>> = entries.iterator()
@kotlin.internal.InlineOnly
public inline operator fun <K, V> Map.Entry<K, V>.component1(): K = key
@kotlin.internal.InlineOnly
public inline operator fun <K, V> Map.Entry<K, V>.component2(): V = value
因此你可以用for循環方便的讀取map(或者其他數據集合)
Ranges
- Ranges
- 工作原理
- 範圍指標
- 常見的接口的定義
- 類的實現
- 一些使用函數
Ranges
Range表達式是通過rangeTo函數形成的。rangTo函數擁有形如…的操作符,改操作符是用in和!in實現的。
Range可以對任何可比較的類型做操作,但對整數基本類型是優化過的。下面是些例子:
//Ranges
fun getRangesTest(){
val i = 0
if (i in 1..10){
println("$i")
}
val test=1.0
if (test !in 1.0..3.0){
println(test)
}
val str="isLb"
if (str in "isLand".."isLe")
println(str)
}
輸出結果
isLb
數字的範圍有個附加特性:他們可迭代。編譯器會把它轉成類似java的for循環的形式,且不用擔心越界:
在剛纔的例子中for循環只能執行Int類型數字的循環而無法完成double類型和String類型的循環,因爲默認double和String沒有對應的iterator表達式
//for循環
for (x in 1..5) println(x)
val testFor= listOf(1.0,2.0)
for (x in testFor) println("$x")
輸出結果
1
2
3
4
5
1.0
2.0
錯誤事例:
for (x in "isLand".."isLe") println(x)
**錯誤原因:**String類型沒有iterator表達式
/Users/wyc/androidstudio project/kotlinproject/accounschool_kotlin/trunk/app/src/main/java/com/wyc/accountschool/kotlin/test/TestDelegate.kt: (376, 14): For-loop range must have an 'iterator()' method
但是有個以爲爲什麼if
可以呢????
如果你想迭代數字並反過來,可以使用downTo()
函數
//倒序數列
for (x in 6 downTo 1) println(x)
輸出:
6
5
4
3
2
1
也可以使用指定步數迭代**step()
**
for(x in 1..4 step 2)print(x)
輸出:
13
工作原理
在標準庫中有兩種接口:Range
和Progression
Range標識數學範圍上的一個見哥。它有兩個端點:start和end。主要的操作符是contains通常在in/!in操作腹內;
Progression表示一個算數級數。它有一個start和end以及一個非零increment。Progression是Iterable的一個子類,因此可以使用在for循環中,或者map filter等等第一個元素是start下一個元素都是前一個元素的increment。Progression
的迭代與java/javaScript的for循環相同:
// if increment > 0
for (int i = start; i <= end; i += increment) {
// ...
}
// if increment < 0
for (int i = start; i >= end; i += increment) {
// ...
}
範圍指標
例子:
if (str in "island".."isle") println(str)
// Iterating over arithmetical progression of numbers. Optimized for number primitives (as indexed for-loop in Java).
for (i in 1..4) print(i) // prints "1234"
for (i in 4..1) print(i) // prints nothing
for (i in 4 downTo 1) print(i) // prints "4321"
for (i in 1..4 step 2) print(i) // prints "13"
for (i in (1..4).reversed()) print(i) // prints "4321"
for (i in (1..4).reversed() step 2) print(i) // prints "42"
for (i in 4 downTo 1 step 2) print(i) // prints "42"
常見的接口的定義
兩種基本接口:Range
Progression
**Range
接口:**定義了一個單位或者數學意義上的一個間隔。
public interface ClosedRange<T: Comparable<T>> {
/**
* The minimum value in the range.
*/
public val start: T
/**
* The maximum value in the range (inclusive).
*/
public val endInclusive: T
/**
* Checks whether the specified [value] belongs to the range.
*/
public operator fun contains(value: T): Boolean = value >= start && value <= endInclusive
/**
* Checks whether the range is empty.
*/
public fun isEmpty(): Boolean = start > endInclusive
}
Progression
定義了數學上的級數。包括start end increment 端點。最大的特點就是它可以迭代,因此它是Iterator的子類。end不是必須的
在Kotlin1.3中已經沒有單獨定義Progression方法,不過爲不同的類型建立了不同的Progression:CharProgression,IntProgression,LongProgression…
類的實現
IntProgression爲例創建構造函數,使用rangeTo() , downTo() , reversed(), stop()實用函數
public open class IntProgression internal constructor(
start: Int,
endInclusive: Int,
step: Int
) : Iterable<Int> {
init {
if (step == 0) throw kotlin.IllegalArgumentException("Step must be non-zero.")
if (step == Int.MIN_VALUE) throw kotlin.IllegalArgumentException("Step must be greater than Int.MIN_VALUE to avoid overflow on negation.")
}
override fun iterator(): IntIterator = IntProgressionIterator(first, last, step)
}
IntRange
實現了Progression<Int>
Range<Int>
接口,因爲它天生一通過range迭代(默認增加值1):
public class IntRange(start: Int, endInclusive: Int) : IntProgression(start, endInclusive, 1), ClosedRange<Int> {
}
ComparableRange
也很簡單
/**
* Represents a range of [Comparable] values.
*/
private open class ComparableRange<T : Comparable<T>>(
override val start: T,
override val endInclusive: T
) : ClosedRange<T> {
override fun equals(other: Any?): Boolean {
return other is ComparableRange<*> && (isEmpty() && other.isEmpty() ||
start == other.start && endInclusive == other.endInclusive)
}
override fun hashCode(): Int {
return if (isEmpty()) -1 else 31 * start.hashCode() + endInclusive.hashCode()
}
override fun toString(): String = "$start..$endInclusive"
}
一些實用的函數
rangeTo()
rangeTo
函數僅僅是調用*Range的構造函數,比如:
針對Int現在由於Int自帶Iterator已經不需要rangeTo來實現了
downTo()
downTo()
擴展函數可以爲任何數字類型定義
public infix fun Int.downTo(to: Int): IntProgression {
return IntProgression.fromClosedRange(this, to, -1)
}
reversed()
reversed()
擴展函數時給所有的*Range
和*Progression
類定義的,並且他們都是反向級數
public inline fun String.reversed(): String {
return (this as CharSequence).reversed().toString()
}
step()
step()
擴展函數是給所有的*Range
和*Progression
類定義的,所有的返回級數都修改了step值。注意:step值總是正的,否則函數不會改變迭代的方向
step()擴展函數是給所有的
*Range和
*Progression`類定義的,所有的返回級數都修改了step值。注意:step值總是正的,否則函數不會改變迭代的方向
/**
* Returns a progression that goes over the same range with the given step.
*/
public infix fun IntProgression.step(step: Int): IntProgression {
checkStepIsPositive(step > 0, step)
return IntProgression.fromClosedRange(first, last, if (this.step > 0) step else -step)
}