Swift與Objective-C的對比,SwiftObjective-C

來源:互聯網
上載者:User

Swift與Objective-C的對比,SwiftObjective-C

WWDC 2014上蘋果再次驚世駭俗的推出了新的程式設計語言Swift 雨燕, 這個訊息會前沒有半點鐘風聲的走漏。訊息發布當時,會場一片驚呼,相信全球看直播的碼農們當時也感覺腦袋被敲了一記悶棍吧。於是熬夜學習了Swift大法, 越看越想高呼 ” Swift大法好!“

 

程式員,最講究的就是實事求是和客觀,下面就開始對比兩種語言。

 

首先要強調的是,Swift絕對不是解釋性語言,更不是指令碼語言,它和Objective-C,C++一樣,編譯器最終會把它翻譯成C語言,也就是 說編譯器最終面對的其實都是C語言代碼( 這是千真萬確,不容置疑的!!!所以不要看它長的想指令碼語言,其實它是比Java, C#要高效的多的C語言!!!),但是Swift的強大之處在於它站在所有語言的肩膀上,吸取所有語言的精華。

 

這個系列我們先談談幾個最基本的文法變化:

但蘋果不會這麼自甘平庸,我們知道Objective-C裡方法的調用有種文法是其他主流語言沒有的,那就是標籤。我們在使用java, C++, C, C#等語言時,如果使用 rect.set( 10, 20, 100, 500 ), 雖然在寫set方法的時候,IDE有提示四個形參的含義,但寫完後,這句代碼中10, 20, 100, 500是社麼意思? 所以代碼的可讀性就變的很差, 而Objective-C很完美的解決了這個問題 :

C代碼  
  • [ rect setX:10 y:20 width:100 height:500 ]  
  • [ rect setX:10 y:20 width:100 height:500 ]

     

     

    看看!多棒!Swift當然不會丟棄這麼好的傳統, 在Swift中是這個樣子的

    C代碼  
  • rect.set( 10, y:20, width:100, height:500 )  
  • rect.set( 10, y:20, width:100, height:500 )

     

     

    對於調用方法時,標籤的使用需要注意以下兩點:

     

    1)全域函數的調用,不可以使用標籤

    2 ) 類的函數,第一個參數不可以加標籤

     

    其實Swift中對類的定義和java, c#幾乎一樣,再也不分標頭檔和.m檔案了。

    一個類的定義文法如下:

    C代碼  
  • class Weapon  
  • {  
  •     var name:NSString  
  •     var power:int  
  •     init( name:NSString, power:int )  
  •     {  
  •         self.name = name  
  •         self.power = power  
  •     }  
  •     func shoot( )  
  • }  
  • class Weapon{    var name:NSString    var power:int    init( name:NSString, power:int )    {        self.name = name        self.power = power    }    func shoot( )}

     

    注意:Swift中的語句不需要分號結束.

    其次,終於有建構函式和解構函式了!!!Objective-C也有?no no no!!!

    Objective-C中沒有建構函式,真正的建構函式是系統自動調用的,而不是強迫程式員去調用。以前要強迫程式員[ [ Obj alloc ] init ],現在終於終於終於系統自動調用了!

    C代碼  
  • Weapon weapon = Weapon( name:“人間大炮”, power: 100000000000 )  
  • Weapon weapon = Weapon( name:“人間大炮”, power: 100000000000 )

     

    我沒有寫錯, 對的!現在和java,C#一樣!雖然weapon是一個指標,但不要寫那顆星號!!因為這顆星號嚇死過好多人!“ 啥?指標?!!啊。。。。。”

     

    C、 C++的程式員注意了,這個weapon對象不是分配在棧記憶體上的, 仍然是alloc出來的, 在堆上呢。

    對於override在Java,C++,Objective-C中都有問題,舉個栗子:

    C代碼  
  • @interface Weapon  
  • -(void)shoot;  
  • @end  
  • @interface Gun : Weapon  
  • -(void)Shoot;  
  • @end  
  • @interface Weapon-(void)shoot;@end@interface Gun : Weapon-(void)Shoot;@end

     

    在大項目中經常會遇到這個問題,程式員的本意是希望覆蓋父類的shoot ,結果手潮。。。。寫成了Shoot , 這既沒有語法錯誤,也沒有邏輯錯誤,結果在

    C代碼  
  • Weapon*  currentWeapon = [ Gun new ];  
  • Weapon*  currentWeapon = [ Gun new ];

     

    [currentWeapon shoot ] 中調用的卻是父類的shoot方法( 因為子類根本沒有覆蓋啦,子類大小寫不小心寫錯了 ), 這種小錯誤如果出現在超大型項目種還真是很難找呢!!現在,Swift終於解決這個問題啦! 子類覆蓋父類方法的時候,一定要在方法前寫上override :

    C代碼  
  • override func shoot{  
  • }  
  • override func shoot{}

     

    這樣,編譯器一看方法前寫了override, 它就會在父類中去尋找是否有shoot方法, 如果你寫錯成override func Shoot, 那編譯器就立刻能發現報錯啦!

     

    系列(二)

     

    系列一發表後,有人不同意我的關於 #swift會取代objective-c#的論點,在這裡我想強調兩點:

     

    1)Swift其實就是Objective-C的文本變種,對於這門全新的語言,蘋果做的工作其實遠沒有我們想像的艱巨。LLVM編譯器做工作只是 先把swift翻譯成Objctive-C代碼,然後再把Objective-C代碼翻譯成C語言代碼,然後再把C語言代碼翻譯成彙編,最終翻譯成機器 碼。至於為什麼編譯器廠商這麼繞,不直接把自己的語言翻譯成彙編和機器碼,那是由於現有的語言編譯器(Objective-C, C )已經非常成熟,而進階語言間的文本轉換開發成本和維護成本都極其小。Swift為什麼要翻譯成Objective-C,是由於Swift仍然需要 Objective-C中辛苦構建的ARC,GCD 等環境。

     

    2)既然Swift代碼最終會被LLVM翻譯成Objective-C, 那Swift語言還有什麼意義?想想ARC剛出來的時候大家的反應吧,很多人和今天的反應一樣,認為我是資深的objective-c馬仔了,我深諳記憶體 管理之道,不停的寫[ obj release ], [ obj autoRelease] 很牛,只有那些初學者才會用ARC呢。結果就是不到一年,ARC統治了整個馬仔界,因為我們馬仔關注的應該是商務邏輯,而不應該把精力分散在文法等低級問 題上,文法消耗我們的時間越少,這門語言就越成功。

     

    既然Swift其實就是Objective-C, 對入門者而言遠比Objective-C好學,對資深開發人員來說又能節約很多無謂的低級重複的機械代碼(這些代碼在LLVM翻譯成Objective-C 時,編譯器自動幫你寫上)。我是想不出任何一點Swift不替換Objective-C的理由呢。

     

    好吧,爭論放置一邊不表,我們從頭來看swift到底進化到什麼程度。

    1)語句不需要分號結束,變數如果有初始化就不需要類型

    C代碼  
  • var n = 22  
  • var n = 22

     

    對於編譯器而言,既然你都初始化為22了,它當然明白n是int , 你都打斷行符號了, 它當然知道這是語句的結束,所以LLVM毫無壓力的把它翻譯成

    C代碼  
  • int n = 22;  
  • int n = 22;

     

    當然對於多個語句放一行,那編譯器就沒有辦法了, 你還是要用分號來結束語句。如果沒有初始化,你也可以手工指定變數類型

    C代碼  
  • var n = 22; var hero:Hero  
  • var n = 22; var hero:Hero

     

    所以看上去是無類型變數,實質上還是強型別的( 編譯器給你做了 ).

    如果是常量的話, 用let

    C代碼  
  • let PI = 3.1415926  
  • let PI = 3.1415926

     

    這裡的PI 就是常量, 現在想想,以前的強型別進階語言真是傻到無語啊,let PI = 3.1415926 , PI  都這麼明顯是個double, 為啥還要程式員再寫double ?!

     

    2)函數的定義

    C代碼  
  • func test( p1: int, p2: int )  
  • {  
  • }  
  • func test( p1: int, p2: int ){}

     

    調用: test( 25 , 100 ) //注意:全域函數的調用,參數不能加標籤

    如果有傳回值, 傳回型別用符號 “ -> ” 表示

    C代碼  
  • func  add( p1: int, p2 : int )->int  
  • {  
  •     return p1+p2  
  • }  
  • func  add( p1: int, p2 : int )->int{    return p1+p2}

     

    3)類的定義

    不再分標頭檔和m檔案了!這點和java, C#一模一樣

    C代碼  
  • class Person  
  • {  
  •     var    name:String  
  •     var    age = 0  
  •     init( name:String , age:int )  
  •     {  
  •         self.name = name;  
  •         self.age = age;  
  •     }  
  •     func description( )->String  
  •     {  
  •         return “Name:\( self.name ) ; Age: \( age )”;  
  •     }  
  • }  
  • class Person{    var    name:String    var    age = 0    init( name:String , age:int )    {        self.name = name;        self.age = age;    }    func description( )->String    {        return “Name:\( self.name ) ; Age: \( age )”;    }}

     

    注意終於有建構函式了!!init 是系統自動調用的, 不需要程式員手工調用。所以它寫起來和普通函數也有區別,前邊不能加func。 編譯器為什麼要這樣做?因為如果init也允許前面加上func, 萬一程式員不小心把init函數名寫錯了, 寫成func Inot( ),編譯器就完全不知道它是程式員想寫的建構函式。現在建構函式前不加func , 如果你寫成Inot( ) 。 編譯器一看前面沒有func知道你要寫構造,可函數名又不是init, 編譯器就知道你不小心寫錯了就可以立刻報錯啦!!

     

    4)可選變數# ---所有進階語言一開始就遇到的難題

    比如客戶需要提供一個最終的API, 客戶給你一個資料來源, 需要在資料來源裡找到名字是“jack.xu”的學員成績。這個api的設計應該是這樣的:

    C代碼  
  • int FindScoreByName( DataSource*  source, string* name );  
  • int FindScoreByName( DataSource*  source, string* name );

     

    問題來了,如果“jack.xu”的學員根本不存在,應該返回啥? 返回0?那肯定不對,因為0有可能也是學員的成績。當然,如果返回的是類的對象,直接返回 NULL , 調用者就知道沒有找到,現在是基礎資料型別 (Elementary Data Type),返回NULL 其實就是0,怎麼辦?(在C,C++中的規範做法是 返回bool表示是否找到,而成績通過形參來傳遞 ,其他進階語言中可以封裝一個小類/包裹類 )

     

    Swift針對這個問題,專門設計了一個叫”optional value(可選變數)”  的變數,它就是為瞭解決這個問題的。

    文法:

    C代碼  
  • var n : UInt ? = 5    或者  var n ? = 5  
  • var n : UInt ? = 5    或者  var n ? = 5

     

    這裡的?表示n 是個可選變數, 也就是說 n 有可能不存在, 什麼情況下n不存在呢?

    如果你這樣寫:

    C代碼  
  • var n : UInt ?  
  • var n : UInt ?

     

    此外,需要注意的是swift文法中,nil 並不是0 , 而是一個NilType類型的變數

    所以上面提到的那個問題就可以很容易解決了

    C代碼  
  • func FindScoreByName( source:DataSource, name:String )->UInt?  //返回的是可選變數  
  • {  
  •     var score : UInt ?; //此時 score 的變數沒有分配記憶體,也就是說score為nil  
  •     if( source.HasStudent( name: name ) )  
  •         score = source[ name ]. score;  //這裡score才分配記憶體;  
  •     return score; //如果沒有找到學生資訊, score的記憶體一直沒被分配  
  • }  
  • func FindScoreByName( source:DataSource, name:String )->UInt?  //返回的是可選變數{    var score : UInt ?; //此時 score 的變數沒有分配記憶體,也就是說score為nil    if( source.HasStudent( name: name ) )        score = source[ name ]. score;  //這裡score才分配記憶體;    return score; //如果沒有找到學生資訊, score的記憶體一直沒被分配}

     


    蘋果推出Swift,還有沒有必要學objective-c

    沒有,按apple的說法,Swift在各方面要優於objective-c,既然有更好的,為什麼還要學習老舊、效能低下的呢?
    objective-c的優勢是很成熟,但成熟掩蓋不了它的各種缺點,Swift雖然年輕,但可能潛力巨大(潛力是否巨大跟apple的發展關係也很大),畢竟它只適用於apple
    如果你專註於apple開發,還是直接學Swift比較好,先把一門學精,即使需要,再學另一種也很容易。就目前來講,Swift的資料比較少,但是只要你有恒心去學,這應該算不上什麼問題,況且還有apple的大力支援,還有什麼可擔心?
     
    swift與objectiveC有什不同

    當然時物件導向的了。趕緊學吧。蘋果拋出 swift 後面就是逐步拋棄 Objective-C 了。
     

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.