github地址
函式和 Lambda 表示式
- Lambda 表示式
- 行內函數
函式的中綴表示法
- 首先說它的使用條件:
- 他們是成員函式或擴充套件函式
- 他們只有一個引數
- 他們用 infix 關鍵字標註
- 實際用法:我們先看看幾個kotlin的原始碼
/** Shifts this value left by [bits]. */
public infix fun shl(bitCount: Int): Int
/** Shifts this value right by [bits], filling the leftmost bits with copies of the sign bit. */
public infix fun shr(bitCount: Int): Int
/** Shifts this value right by [bits], filling the leftmost bits with zeros. */
public infix fun ushr(bitCount: Int): Int
/**
* Creates a tuple of type [Pair] from this and [that].
*
* This can be useful for creating [Map] literals with less noise, for example:
* @sample samples.collections.Maps.Instantiation.mapFromPairs
*/
public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)
/**
* Returns a set containing all elements that are contained by both this set and the specified collection.
*
* The returned set preserves the element iteration order of the original collection.
*/
public infix fun <T> Iterable<T>.intersect(other: Iterable<T>): Set<T> {
val set = this.toMutableSet()
set.retainAll(other)
return set
}
/**
* Returns a progression from this value down to the specified [to] value with the step -1.
*
* The [to] value has to be less than this value.
*/
public infix fun Short.downTo(to: Short): IntProgression {
return IntProgression.fromClosedRange(this.toInt(), to.toInt(), -1)
}
`複製程式碼
從原始碼中可以看出 infix 的用法:當我們定義一個類的函式或者擴充套件函式的時候,如果這個函式接受的引數和自己是同一類的,並且又反回值那麼就採用中綴表示法
高階函式與 lambda 表示式
- 這節內容有的人可能有的學習起來會覺得有點難,其實只要轉變一下觀點記住下面的幾點,就很簡單了。看完後就可以愉快的看kotlin原始碼學習了。
- 一個 lambda 表示式或匿名函式是一個“函式字面值(字面函式)”,即一個未宣告的函式,做為表示式傳遞。
- 函式型別:() -> T
- kotlin 原始碼大量採用了lambda表示式,這樣說明以後自己在寫程式碼的時候,必然也會用到很多,這個也很簡單,我們記住這點:將函式用作為引數或返回值的函式是 高階函式,kotlin一般採用函式字面值(字面函式)的方式往高階函式傳參,一個高階函式接受另一個lambda 表示式作為最後一個引數,lambda 表示式引數可以在
圓括號引數列表之外傳遞。 - kotlin的lambda 表示式和高階函式可以為我們省去以前很多的java介面。下面的介面省掉了OnClickListenter這個介面
//簡單改造view的setOnClickListenter
class Main2Activity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
var view = View()
view.setOnClickListenter {
it->it.toHome()
}
}
}
class View{
fun toHome() {
}
fun setOnClickListenter(listerner: (v:View) -> Unit) {
listerner(this);
}
}複製程式碼
- 接受者 是接受這個函式的物件,也就是呼叫這個函式的物件
- 帶接收者的函式字面值:可以呼叫該接收者物件上的方法而無需任何額外的限定符。這類似於擴充套件函式,它允你在函式體內訪問接收者物件的成員。
可以這樣理解,當我們在寫一個高階函式的時候,發覺需要用到lambda 表示式中引數物件裡面的方法的時候,這個時候就用到帶接收者的函式字面值。kotlin原始碼裡 面很多這樣的函式,下面舉例說明:
/**
* Calls the specified function [block] with the given [receiver] as its receiver and returns its result.
*/
@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
/**
* Calls the specified function [block] with `this` value as its receiver and returns `this` value.
*/
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
/**
* Calls the specified function [block] with `this` value as its argument and returns `this` value.
*/
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) -> Unit): T { block(this); return this }複製程式碼
然而這裡幾個函式在我們專案中會經常用到,比如這樣:現在有一本書,我要更具他現在的價格來分類,分完之,還要的得到這麼書的名字
class Main2Activity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
var book = Book()
var name = book.apply {
var price = getPrice()
if (price < 50) {
Toast.makeText(this@Main2Activity,"小於50", Toast.LENGTH_LONG).show()//this@Main2Activity 是this表示式
type = "便宜書"
}else{
Toast.makeText(this@Main2Activity,"大於50", Toast.LENGTH_LONG).show()
type = "貴書"
}
}.getName()
}
}
class Book{
var type:String? = null
fun getName():String {
return "youxin"
}
fun getPrice():Int {
return 100
}
}複製程式碼
- 接受者 是接受這個函式的物件,也就是呼叫這個函式的物件
- this表示式