有时候可以通过给对象插入多个成员函数做区别是很方便的,比如:
//多重声明
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循环中的使用
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()
的值
//返回两个值,根据数据类来返回,数据类自动声明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最好的办法是下面这样:
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(或者其他数据集合)
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
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
函数仅仅是调用*Range的构造函数,比如:
针对Int现在由于Int自带Iterator已经不需要rangeTo来实现了
downTo()
扩展函数可以为任何数字类型定义
public infix fun Int.downTo(to: Int): IntProgression {
return IntProgression.fromClosedRange(this, to, -1)
}
reversed()
扩展函数时给所有的*Range
和*Progression
类定义的,并且他们都是反向级数
public inline fun String.reversed(): String {
return (this as CharSequence).reversed().toString()
}
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)
}