歡迎加入QQ討論群258996829
月之殘骸 頭像
蘋果2袋
2
月之殘骸

從Java到Swift

發(fā)布時(shí)間:2016-03-15 20:06  回復(fù):1  查看:4941   最后回復(fù):2016-03-17 22:12  
我們學(xué)習(xí)的新事物時(shí),通常并不是從0開始,而是從已知開始,將新事物與已知的進(jìn)行比較分析,從而快速全面地了解新事物。

而我熟悉Java,所以在學(xué)習(xí)Swift時(shí),就會(huì)將Swift與Java進(jìn)行比較,思考。(文中的示例代碼均來(lái)自The Swift Programming Language

概覽

從Java到Swift還是比較簡(jiǎn)單的,相比Object-C,Swift和Java的語(yǔ)法更加接近,和最近的Kotlin就更像了。Swift同時(shí)支持面向?qū)ο缶幊毯秃瘮?shù)式編程。Swift比Java功能更加強(qiáng)大,用法更加友好。網(wǎng)上有一份Java和Swift的粗略對(duì)比:
java vs swift

基礎(chǔ)部分

1.Swift沒(méi)有main函數(shù),這個(gè)有點(diǎn)像腳本語(yǔ)言。Swift程序的默認(rèn)入口是main.swift文件,在iOS應(yīng)用中,則通常標(biāo)記了@UIApplicationMain的AppDelegate.swift文件。可以類比到Android中,在AndroidManifest.xml中定義的Application。
2.Swift不需要定義行結(jié)束符,這個(gè)是像腳本語(yǔ)言一樣。

3.Swift使用var定義變量,一般無(wú)需指定具體的數(shù)據(jù)類型,編譯器會(huì)自行判斷。遇到編譯器無(wú)法判斷的情況,需要自己顯式指定。

//Java定義變量
int x = 0;

//Swift定義變量,編譯器自動(dòng)識(shí)別數(shù)據(jù)類型
var x = 0;

//Swift定義變量,顯式指定類型,否則此時(shí)編譯器會(huì)自動(dòng)識(shí)別成Int
var y : Long = 0;

4.Swift用let定義常量,Java里面是static final。
5.array跟Java中的array是一樣的概念。dictionary就是Java中的map。dictionary的取值的方式是dictionary[key],接口就像array一樣,簡(jiǎn)潔方便。
6.nil在swift中就類似Java中的null。nil是沒(méi)有初始化成功,是沒(méi)有值。
7.optional value是指該value的值可以是nil,Swift默認(rèn)一個(gè)var是不能賦值nil,除非它聲明了optional。optional不能直接輸出,而必須unwrap,形如optionalValue!。有點(diǎn)類似于Java中打包好的null判斷。也可以用!代替?聲明一個(gè)無(wú)需unwrap的var。

邏輯控制

1.Swift的switch 語(yǔ)法和Java及C++很像,但是它沒(méi)有break,他命中一個(gè)case后會(huì)自動(dòng)退出switch。對(duì)于幾個(gè)不同case同樣處理的情況,可以case后面連續(xù)幾個(gè)condition,用逗號(hào)隔開。

switch value {
case condition1:
    response to condition 1
case condition2, condition3:
    resoponse to condition 2 or 3
default:
    otherwise, do something else
}
2.Swift的switch支持運(yùn)算,運(yùn)算的話,就是說(shuō)不僅僅是equal,而是支持滿足特定要求。
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
    print("(\(x), \(y)) is on the line x == y")
case let (x, y) where x == -y:
    print("(\(x), \(y)) is on the line x == -y")
case let (x, y):
    print("(\(x), \(y)) is just some arbitrary point")
}
// prints "(1, -1) is on the line x == -y"

3.while循環(huán)和Java或者C++中基本一致,不過(guò)while后面直接寫condition,不需要用括號(hào)。
4.for循環(huán)和Java也基本一樣,不過(guò)也是不需要括號(hào)。for循環(huán)中,..<的用法比較方便。下劃線符號(hào)_(替代循環(huán)中的變量)能夠忽略具體的值,并且不提供循環(huán)遍歷時(shí)對(duì)值的訪問(wèn)。for-in則有點(diǎn)類似與Java中for each循環(huán)。

函數(shù)

1.函數(shù)的定義和Java很不一樣。Swift函數(shù)的定義形如 func functionName(argName: Type) -> Return Type:

func sayHelloAgain(personName: String) -> String {
    return "Hello again, " + personName + "!"
}
2.Swift函數(shù)可以返回多個(gè)返回值,這個(gè)功能真是太猛了。
func minMax(array: [Int]) -> (min: Int, max: Int) {
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array[1..<array.count] {
        if value < currentMin {
            currentMin = value
        } else if value > currentMax {
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}
3.Swift函數(shù)可以接收不定參數(shù),跟Java基本類似的用法。
4.函數(shù)可以嵌套,這個(gè)是Java或者C++都沒(méi)有的,挺好用。例如經(jīng)常有一段邏輯,用一個(gè)函數(shù)實(shí)現(xiàn)太長(zhǎng),在Java或者C++中,通常是會(huì)把它拆分成幾個(gè)函數(shù),保持每個(gè)函數(shù)短小,功能單一。但是這樣拆分的函數(shù)并不能很好的表明他們是一個(gè)功能的,不夠“內(nèi)聚”。用這種Swift函數(shù)嵌套的方式就能較好實(shí)現(xiàn)。
func chooseStepFunction(backwards: Bool) -> (Int) -> Int {

    func stepForward(input: Int) -> Int { 
        return input + 1 
    }

    func stepBackward(input: Int) -> Int { 
        return input - 1 
    }

    return backwards ? stepBackward : stepForward
}
5.Swift支持函數(shù)類型,根據(jù)輸入?yún)?shù)和返回值確定一個(gè)函數(shù)類型。函數(shù)類型可以讓函數(shù)像,普通數(shù)據(jù)類型一樣使用。例如函數(shù)的參數(shù)可以另外一個(gè)函數(shù),注意,不是另外一個(gè)函數(shù)的返回值,而是另外一個(gè)函數(shù),只要類型符合即可。這個(gè)相當(dāng)于是函數(shù)級(jí)別的多態(tài),真的有點(diǎn)猛。
//定義一個(gè)函數(shù),類型是(Int, Int)->Int
func addTwoInts(a: Int, _ b: Int) -> Int {
    return a + b
}

//定義另一個(gè)函數(shù),其中一個(gè)參數(shù)是(Int, Int) -> Int函數(shù)
func printMathResult(mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
    print("Result: \(mathFunction(a, b))")
}

//直接將addTwoInts()作為printMathResult()的參數(shù)
printMathResult(addTwoInts, 3, 5)

6.Swift支持閉包,我覺(jué)得可以理解成“匿名函數(shù)”,只需要描述輸入輸出,用in分開輸入輸出描述,已經(jīng)函數(shù)體,無(wú)需定義函數(shù)名。

類與結(jié)構(gòu)

1.類的構(gòu)造函數(shù),直接叫init()。類函數(shù)調(diào)用跟Java,C++基本一樣。self相當(dāng)于Java中的this。
2.在Swift中class的成員訪問(wèn)權(quán)限控制級(jí)別有public, internal, private,類似Java中的public, protected, private。
3.deinit是析構(gòu)函數(shù)。Java中也有finalize()函數(shù)。不過(guò)Java的finalize()函數(shù)并不確保一定被調(diào)用,所以并不推薦override該函數(shù)。
4.類的繼承跟C++有點(diǎn)像,使用:。

class SomeSubclass: SomeSuperclass {
    // subclass definition goes here
}
5.他的setter和getter函數(shù)跟Java不太一樣,是隱式調(diào)用的。我覺(jué)得Swift的設(shè)計(jì)思想是,用戶只需關(guān)心輸入和輸出,其他的不用關(guān)心。例如此處只需關(guān)心需要set或者get。具體的set和get函數(shù)則是封裝的,無(wú)需使用者去關(guān)心。又譬如上面提到的method的type,只要定義了輸入和輸出,就定義了一類method,那就可以對(duì)這種type有多種具體實(shí)現(xiàn)。
struct Point {
    var x = 0.0, y = 0.0
}
struct Size {
    var width = 0.0, height = 0.0
}
struct Rect {
    var origin = Point()
    var size = Size()
    var center: Point {
        get {
            let centerX = origin.x + (size.width / 2)
            let centerY = origin.y + (size.height / 2)
            return Point(x: centerX, y: centerY)
        }
        set(newCenter) {
            origin.x = newCenter.x - (size.width / 2)
            origin.y = newCenter.y - (size.height / 2)
        }
    }
}

var square = Rect(origin: Point(x: 0.0, y: 0.0),
    size: Size(width: 10.0, height: 10.0))
let initialSquareCenter = square.center
square.center = Point(x: 15.0, y: 15.0)
print("square.origin is now at (\(square.origin.x), \(square.origin.y))")
6.Swift的枚舉和Java類似,本質(zhì)是一個(gè)類,里面可以包含函數(shù)。
7.Swift的struct和class寫法基本一樣,區(qū)別在于struct傳遞的是內(nèi)容的copy,而class傳遞的是引用。這個(gè)厲害啊。
8.枚舉還支持associated value,這個(gè)是Java沒(méi)有的。
enum Barcode {
    case UPCA(Int, Int, Int, Int)
    case QRCode(String)
}

var productBarcode = Barcode.UPCA(8, 85909, 51226, 3)
9.protocol類似于Java中的interface。
10.extension比較強(qiáng)大,甚至變態(tài),可以動(dòng)態(tài)往某個(gè)類中增添函數(shù)以及成員變量,動(dòng)態(tài)讓某個(gè)類實(shí)現(xiàn)某個(gè)protocol,而無(wú)需修改該類源代碼。Java新增成員變量,新增函數(shù),實(shí)現(xiàn)某個(gè)interface,Java都只能通過(guò)繼承實(shí)現(xiàn)。而這個(gè)直接實(shí)現(xiàn),且對(duì)一切該類的對(duì)象生效,包括extend之前已經(jīng)創(chuàng)建的對(duì)象。
extension Double {
    var km: Double { return self * 1_000.0 }
    var m: Double { return self }
    var cm: Double { return self / 100.0 }
    var mm: Double { return self / 1_000.0 }
    var ft: Double { return self / 3.28084 }
}
let oneInch = 25.4.mm
print("One inch is \(oneInch) meters")
// prints "One inch is 0.0254 meters"
let threeFeet = 3.ft
print("Three feet is \(threeFeet) meters")
// prints "Three feet is 0.914399970739201 meters"
11.Swift泛型和Java類似的,Swift的泛型支持where語(yǔ)句,可以在對(duì)類型控制之外,作更加精細(xì)的控制。
func allItemsMatch<
    C1: Container, C2: Container
    where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
    (someContainer: C1, _ anotherContainer: C2) -> Bool {

        // check that both containers contain the same number of items
        if someContainer.count != anotherContainer.count {
            return false
        }

        // check each pair of items to see if they are equivalent
        for i in 0..<someContainer.count {
            if someContainer[i] != anotherContainer[i] {
                return false
            }
        }

        // all items match, so return true
        return true

}

內(nèi)存管理

Swift和Java類似,也無(wú)需自己管理內(nèi)存,Swift是由ARC(Automatic Reference Counting)機(jī)制來(lái)回收內(nèi)存的,Java是有垃圾回收機(jī)制來(lái)保證內(nèi)存被及時(shí)回收。但是兩者的回收機(jī)制有所區(qū)別。我的理解是Swift的ARC機(jī)制著眼于無(wú)效的對(duì)象,就是那些沒(méi)有被任何人引用到的對(duì)象。因此,如果兩個(gè)對(duì)象循環(huán)引用,就會(huì)無(wú)法被回收,引起泄露。此時(shí)就需要Weak Reference或者Unowned Reference來(lái)打破這個(gè)環(huán)。
下圖中Person對(duì)象和Apartment對(duì)象由于互相強(qiáng)引用,無(wú)法被ARC回收。
screenshot

而Java的垃圾回收機(jī)制,從反面思考,著眼于哪些是有效的對(duì)象,即有被GC Root引用到的對(duì)象是有效的,其他的都是無(wú)效的。因此哪怕有對(duì)象相互引用,只要沒(méi)有被GC Root引用到,都會(huì)被垃圾回收器回收掉(如下圖所示)。從這此處來(lái)看,Java的策略更優(yōu)。也由此可以看到換個(gè)角度看問(wèn)題是多么重要。
screenshot

參考引用

  1. The Swift Programming Language (Swift 2.1)https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/index.html#//apple_ref/doc/uid/TP40014097-CH3-ID0
  2. what is the entry point of swift code execution? http://stackoverflow.com/questions/24105690/what-is-the-entry-point-of-swift-code-execution
  3. Swift程序入口深度分析 http://00red.com/blog/2014/11/20/swift-main-study/
  4. Swift 函數(shù)式編程實(shí)踐 http://codebuild.me/2015/09/15/swift-functional-programming-intro/
  5. Java vs Swift http://slidenerd.com/2014/11/15/swift-vs-java/
  6. SwiftGuide https://github.com/ipader/SwiftGuide
  7. Swift https://developer.apple.com/swift/
  8. Learn the Essentials of Swifthttps://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/DevelopiOSAppsSwift/Lesson1.html
  9. What is an “unwrapped value” in Swift? http://stackoverflow.com/questions/24034483/what-is-an-unwrapped-value-in-swift
  10. 自動(dòng)引用計(jì)數(shù) https://numbbbbb.gitbooks.io/-the-swift-programming-language-/content/chapter2/16_Automatic_Reference_Counting.html


分享自:https://yq.aliyun.com/articles/7567
贏了現(xiàn)在輸了未來(lái) 頭像
蘋果2袋
2
贏了現(xiàn)在輸了未來(lái)   2016-03-17 22:12

寫得不錯(cuò),我也搞過(guò)Java。

您還未登錄,請(qǐng)先登錄

熱門帖子

最新帖子

?