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 Range接口,因为它天生一通过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)
}

你可能感兴趣的:(Kotlin,学习,基础学习,Kotlin,Kotlin学习文档,Kotlin灯饰,Kotlin多重声明,Kotlin反射)