Kotlin, Android的Swift

yuyue007 10年前發布 | 34K 次閱讀 Kotlin Swift Android開發 移動開發

來自: http://www.cnblogs.com/sunshine-anycall/p/5223158.html

Kotlin, Android的Swift

蘋果已經用Swift代替Objective-C,一種古老的語言,來進行iOS的開發了。明顯Android開發也有這個趨勢。

雖然現在已經可以選擇Scala或者Groovy等基于JVM的語言開發Android應用來嘗嘗鮮,但是弊端卻顯而易見。

要引入一個全新的開發語言,那么就意味著需要引入這個語言的全部的運行時。這簡直就是噩夢。因為這會給

極大的增加應用包的大小,還不說65535方法問題。小的應用還可以,但是這不是一個合適的替代語言應該有的問題。

Kotlin

介紹一下Kotlin--一個基于JVM的語言。由JetBrains(他們開發了IntelliJ IDEA的一個系列和Android Studio)

開發,并由圣彼得堡附近的一個小島命名,負責這個項目的開發團隊就在這個小島辦公。在2011年為外界

所致,并在幾年后的第二個里程碑(M2)發布了對Android的支持(翻譯的時候已經發布了1.0正式版)。

特性

這個新的語言有什么特色呢,你可能會問。有很多!不過本文會集中講述Java應該有而一直沒有的上面。

命名和可選參數

命名參數是一個很簡單的語言特性,但是卻讓代碼更加易讀,尤其是那些有很多參數的函數簽名。

看下面的例子:

void circle(int x, int y, int rad, int stroke) {
    ...
}

在java調用的時候看起來是這個樣子的:

circle(15, 40, 20, 1);

要多次查看函數簽名才能知道每個參數的具體作用。在Kotlin里,定義是這樣的:

fun circle(x: Int, y: Int, rad: Int, stroke: Int) {
    ...
}

調用就更好了:

circle(15, 40, rad = 20, stroke = 1)

假設我們現在需要把 stroke 參數設定為可選的,在Java里你只能overload出另一個方法,這個方法

少一個參數,然后在里面調用第一個方法:

public void circle(int x, int y, int rad, int stroke) {
    ...
}

public void circle(int x, int y, int rad) {
    circle(x, y, rad, 1);
}

但是在Kotlin里,一切變得簡單:

fun circle(x: Int, y: Int, rad: Int, stroke: Int = 1) {
    ...
}

不是什么大的功能改進,但是Java始終沒有。

Lambda表達式

最近函數式編程日漸流行。Kotlin也支持lambda表達式。

我們先來看一個簡單的。假設你有一個整數列,而且要刪除全部的奇數。

val numbers = listOf(1, 2, 3, 4, 5)

println(numbers.filter { it % 2 != 0 })
// 輸出:[1, 3, 5]

這個函數把list的元素類型為輸入參數類型,這里是integer。并輸出一個boolean型的結果。如果我們把filter的lambda表達式轉化為一個明顯的變量寫出來的就更容易理解了:

val predicate: (Int) -> Boolean = { it -> it % 2 != 0 }
numbers.filter(predicate)

這一語法和其他的而支持lambda表達式的語言的語法相差不大,所以不多做解釋。

Null和類型安全

總是要檢查變量是否為null也是Java里一個很煩人的事。這個問題在Kotlin里被部分解決。

如果你用傳統的方法定義一個變量,那么編譯器是不允許其值為null的。

var text1: String = "something" // 木有問題
var text2: String = null // 無法編譯

那么定義的變量的值需要為null怎么辦呢?你要專門定義一個值可為null的變量。值可為null的變量,用變量類型后面的問號來明確指定。

var text2: String? = null // 木有問題

調用的時候也需要問號。

text2?.replace(" ", "-")

這句的意思是:如果 text2 為空,那么 replace() 方法會被忽略并且不會有 NullPointerException 異常拋出。

如果你接手了一個可選類型(optional type)的變量,你可以百分之百的確認變量的值不會為null(這在Adnroid的API里非常多見,雖然方法定義返回值為空可空類型,但是從來不會返回null),然后可以強制作為非空調用方法。

text2!!.replace(" ", "-")

這個時候,如果 text2 為null的話就會拋出 NulPointerException 異常。所以小心使用。

類型安全的另一個意義是類型檢測。假設你又一個 Context 的實例并且需要檢測這個實例是否為 Activity 類型,然后調用

一些activity才有的方法。

val context = getContext()
if (context is Activity) {
    context.finish()
}

類型檢測之后你就可以把context作為一個activity類型的實例來使用了,不需要強制類型轉換。和Java的

instanceOf 方法一樣, is 也是null安全的。即使 getContext() 返回一個null,上面的代碼也

不會崩潰。

數據對象(Data object)

在寫數據對象的時候,很多你需要手動實現的,比如: toString() , 'hashCode() 以及 equals()`。即使

現在很多的IDE已經減輕了一部分工作量,但是添加了新的成員后再更新這些實現也是非常的麻煩。

Kotlin里不用再為這些操心了。你需要做的只是在類定義的前面加一個 data 的修飾,上面的方法就已經隱式的生成了。

data class Island(val name: String? = null)

如果你初始化上面的類,會自動生成一個人類可以讀懂的 toString() 方法。

val island = Island("Kotlin")
println(island.toString())  // 輸出:Island(name=Kotlin)

同理,如果我們用同一個名字創建另外一個實例,這個實例會 equal 之前創建的實例。并且他們的 hashCode() 值也一樣。

val island = Island("Kotlin")
val island2 = Island("Kotlin")

assert(island.equals(island2))
assert(island.hashCode() == island2.hashCode())

如果你要定制以上的方法,那么,當然,你還是要手寫的。

單例

單例是一個非常常用的方法。Kotlin省去了創建單例的時候需要的靜態 getInstance() 方法和私有的構造函數。

Kotlin使用 object 聲明。

object ApiConfig {
    val baseUrl: String = "https://github.com"
}

object 聲明也可以用來創建靜態方法。

open class MyFragment : Fragment() {
    companion object {
        fun newInstance(): MyFragment = MyFragment()
    }
}

上面的方法可以這樣調用 val fragment = MyFragment.newInstance() ,就和Java的靜態方法一樣。

接口

雖然Kotlin不支持多繼承, 但是還是支持接口的。只不過這個接口和 Trait 比較接近,可以在接口中包括默認實現。

interface SessionCloseable {
    fun closeSession() {
        Log.d(SessionCloseable::class.java.simpleName, "Closing...")
    }
}

以上接口定義了一個可以關閉session的方法,下面我們在一個activity里實現這個方法。

class KotlinActivity : Activity(), SessionCloseable {
    override fun onStop() {
        super.onStop()
        closeSession()
    }
}

有一點需要注意的是Kotlin里沒有extend和implement的區分,什么時候都是逗號分隔。

擴展(extension)

最后我們看一個例子:你可以給一個已經存在的類添加方法。

比如你要創建一個方法,這個方法可以把字符串的空白替換為下劃線。在Java里你需要創建一個Utility的方法,以原始字符串為參數。

public class StringUtils {
    public static String encodeString(String str) {
        return str.replaceAll(" ", "_");
    }
}

在Kotlin里,你可以創建一個擴展方法(extension function),即使原類是 final 的。

fun String.encodeSpaces(): String {
    return this.replace(" ", "_")
}

最后

為了公平起見,以上說到的大部分特性在Java8里都已經有了。但是這些什么時候可以在Android里用到可能

就遙遙無期了(其實這個問題已經有人在2014的Google I/O里問過了,但是根據Xavier Ducrohet的說法近期沒有這樣的計劃)。

還好現在有Kotlin了。

另外,這個語言已經非常的成熟。唯一的問題就是文檔經常補全而且還經常是過期的,不過因為語法和同時JVM語言的Scala多少有些接近,多少可以猜出個大概。所以,這只是一個很小的瑕疵。

最后的最后,Kotlin將會在我(作者)后續的Android開發中盡可能的使用。顯然,對已有的代碼做轉化不太明智。而且Kotlin可以和Java的代碼無縫互操作,這樣不是什么太大的問題。Kotlin很值得一試!

原文 地址 , 代碼在 這里

 本文由用戶 yuyue007 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!