Kotlin研發第十七彈——其他

其他

  • 其他
    • 鏈接

鏈接

  • 多重聲明
  • Ranges
  • 類型檢查和自動轉換
  • This表達式
  • 燈飾
  • 運算符重載
  • 空安全
  • 異常
  • 註解
  • 反射
  • 動態類型

多重聲明

  • 多重聲明
    • 例子:一個函數返回兩個值
    • 例子:多重聲明和Map

多重聲明


有時候可以通過給對象插入多個成員函數做區別是很方便的,比如:

//多重聲明
data class Person(var name:String,var age:Int)
val (name,age)=Person("wyc",27)
println(name)
println("$age")

輸出

wyc
27

多重聲明在一次的活動創建了多個變量,兩個新變量nameage可以獨立使用

多重聲明被編譯成以下代碼:

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

參數abcomponent1()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
工作原理

在標準庫中有兩種接口:RangeProgression

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)
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章