再看了一些Code後常常會看到有一種寫法
啥?
HTML.() -> Unit
這是什麼意思? 如果是
() ->Unit
這我還知道阿,這是lambda function,前面是參數後面是回傳值`,()代表是空參數,如果下面這樣就代表兩個參數A / B 還有回傳C
(A,B) -> C
例如,可以傳入String跟Int,ex.(“name”,15)
(String,Int) -> Unit
但前面多了一個 HTML. 是什麼意思??
這時候想到了extension function,那我是不是可以解讀成
再宣告的當下HTML這個物件,就會透過lambda function擁有後面那個型態的extension function,也就是擁有init的行為
這樣會清楚多了嗎?
平常
fun html(init: () -> Unit): HTML { … }
在前面會多了一個
HTML.
必須解讀成剛剛那句話,
再宣告的當下HTML這個物件,就會透過lambda function擁有後面那個型態的extension function,也就是擁有init的行為
所以在這個裡面,html實體體化後就可以呼叫init()的方法,也就是
html.init()
而通常這樣的方式就稱為 function literals with receiver
可以在官方文件的Lambda章節找到
再談之前先弄懂!
什麼是 literals?
https://semicolonspace.com/kotlin-lambda-function-literals/
查了一下字典他是
The literal meaning of a word is its original, basic meaning.
有點像是,字面的意思、表面的意思~
這樣還是無法懂啊!!
但查了一下Wiki
在電腦中,他是一個固定不可變的值,也就是定義的常數的值,譬如
kotlin
val x = 10
val name = "Tom"
於是乎可以稱為這些為 Int literal / String literal
參考上面網站寫的
被定義出來的就要稱為該型態的literal ,在上面定義講到
“When we assign a function to a variable, it becomes a function literal. Kotlin provides 2 types of function literals.”
當我們指派一個function給一個變數,他就會成是一個function literal,或者也可以當成該變數的實例化結果(如果把他想成一個class的話,但其實這並不正確)
因此呢?
什麼是 function literal ?
也就是一個function types的常數宣告結果
或者是有兩個東西在kotlin中就被稱為function literal
也就是
lambda expression
或是
Anonymous Function
沒有名稱的function
不得不說這是我第一次看到有這樣的寫法,也就是一個沒有function名稱的function,並且可以透過變數來儲存
Function type
Function literals with receiver就是這樣來的https://kotlinlang.org/docs/lambdas.html#function-literals-with-receiver
官方範例就是用html
這樣的使用方式,大部分也被用在type-safe builders 的模式中
function literals with receiver it is possible to create type-safe, statically-typed builders in Kotlin.Type-safe builders allow creating Kotlin-based domain-specific languages (DSLs) suitable for building complex hierarchical data structures in a semi-declarative way
因此這模式就很適合拿來寫DSL語言的方式進行定義,譬如
html{
p{
+"Title"
}
}
如果是從java剛入手的人一定會一頭霧水,啥?這是什麼操作 ,現在你知道原因跟寫法為什麼可以寫成這樣了,但大致上是這樣的概念。
因此剛剛那整段程式碼可以看做成
或是
衍生應用
那看看這個範例, head { } / body{} 這些我都懂了,但那個 +”Xml encoding ..” 是什麼意思? string 是要怎麼用 +????
如果有略懂kotlin就會知道kotlin是可以重寫運算元的
So basically, you just put a string inside a tag body, but there is this little
+
in front of it, so it is a function call that invokes a prefixunaryPlus()
operation.
這解釋了為什麼可以
+ ”This is”
這樣的寫法,更進一步
That operation is actually defined by an extension function
unaryPlus()
that is a member of theTagWithText
abstract class (a parent ofTitle
):
operator fun String.unaryPlus() {
children.add(TextElement(this))
}
So, what the prefix
+
does here is wrapping a string into an instance ofTextElement
and adding it to thechildren
collection, so that it becomes a proper part of the tag tree.
透過這樣定義string的+寫法,他會再+的時後轉變成
產生一個
val textElement = TextElement(this) // this也就是那串字串 "This is"
然後再透過
children.add(textElement)
清楚一點來看是
operator fun String.unaryPlus() {
val textElement = TextElement(this)
children.add(textElement)
}
也就是上面這個定義等同於這樣的描述
+ " This is kotlin”
所以也才能透過
這樣的寫法達成再kotlin中可以寫成類似html的語法,再同一個語言中你可以用kotlin去解決問題,也可以使用類似html語法去建立UI.
以上是個人查看後的一點心得,很多用詞不是很精準,如果有任何錯誤歡迎提出建議修正,感謝各位。
延伸閱讀