swift 3.0 結構體和類 (無腦碼農 VS 技術逼) 的不同理解一

本月在IOS培訓班剛畢業,就出了swift 3.0 .好吧讓我這水平差的自學吧!

咱也"高大上"一回,看看官方文檔,英文看不懂啊!官方文檔地址:https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html#//apple_ref/doc/uid/TP40014097-CH13-ID82

咱有谷歌翻譯啊!我的理想就是先成為一名碼農嘛!

在結構體部分看了快2小時終于明白了,明白什么呢!

技術逼害人啊~


先來看蘋果官方文檔: ? ? ? ? ? ?(碼農們可以直接看最后圖片部分)

(谷歌翻譯的,經過多年鍛煉我已經能看懂各種中文了!)

類和結構

結構是通用的,即成為你的程序的代碼的積木柔性結構。您可以定義屬性和方法,通過使用完全相同的語法為常量,變量和函數將功能添加到您的類和結構。

不像其他的編程語言,斯威夫特不要求你創建單獨的接口和實現文件自定義類和結構。在斯威夫特,你定義一個類或單個文件的結構,外部接口到類或結構的其他代碼使用的是自動提供。

注意

一個實例是傳統上已知的作為對象。然而,斯威夫特類和結構在功能上比其他語言更接近,而很多本章介紹了可以應用到的實例功能,無論是類或結構類型。正因為如此,更普通的術語實例被使用。

比較類和結構

類和結構斯威夫特有許多共同的東西。兩者都可以:

定義屬性來存儲值

限定的方法來提供功能

定義標用標語法,提供訪問其值

定義初始化設置它們的初始狀態

延伸拓展其功能超出了默認的實現

順應協議來提供某一種標準功能

欲了解更多信息,請參見屬性方法下標初始化擴展協議

類具有結構不附加的功能:

繼承允許一個類繼承的另一個特點。

類型轉換可以檢查并在運行時解釋一個類實例的類型。

Deinitializers使類的一個實例,以釋放它已經分配的任何資源。

引用計數允許多個參考一類實例。

欲了解更多信息,請參見繼承類型轉換反初始化,并自動引用計數

注意

當他們在你的代碼通過周圍,也不要使用引用計數的結構總是被復制。

定義語法

類和結構有一個類似的定義語法。你介紹類的class關鍵字和結構的struct關鍵字。無論放置一對大括號內的所有定義:

classSomeClass{

// class definition goes here

}

structSomeStructure{

// structure definition goes here

}

注意

當你定義一個新的類或結構,您可以有效地定義了一個全新的雨燕。給出類型UpperCamelCase名稱(如SomeClass和SomeStructure這里)來匹配標準斯威夫特類型的資本(如String,Int和Bool)。相反,總是給的屬性和方法lowerCamelCase的名稱(如frameRate和incrementCount),從類型名稱區分。

這里有一個結構定義和類定義的例子:

structResolution{

varwidth=0

varheight=0

}

classVideoMode{

varresolution=Resolution()

varinterlaced=false

varframeRate=0.0

varname:String?

}

上面的例子中定義了一個新的結構叫做Resolution,描述一個基于像素的顯示分辨率。這種結構叫了兩個存儲性能width和height。存儲屬性是常量或者被捆綁起來,作為類或結構的一部分存儲的變量。這兩個屬性被推斷為類型Int將它們設置為初始整數值0。

上面還的例子定義了一個名為新類VideoMode,來描述視頻顯示一個特定的視頻模式。這個類有四個變量存儲性能。第一,resolution被初始化一個新的Resolution結構實例,其中推斷的屬性類型Resolution。對于其他三個屬性,新VideoMode實例將與被初始化interlaced設定false(意為“非隔行掃描視頻”)的再現幀速率0.0,和一個可選String稱為值name。在name屬性自動給出的缺省值nil,或“無name值”,是因為它是一個可選的類型。

種類及結構實例

該Resolution結構定義和VideoMode類的定義只說明什么Resolution或者VideoMode看起來像。他們自己不描述具體的分辨率或視頻模式。要做到這一點,你需要創建的結構或類的一個實例。

創建實例的語法為結構和類非常相似:

letsomeResolution=Resolution()

letsomeVideoMode=VideoMode()

結構和類都使用了新的實例初始化程序語法。初始化語法最簡單的形式使用類或結構后跟空括號,如的類型名稱Resolution()或VideoMode()。這將創建類或結構的新實例,與任何屬性初始化為它們的默認值。類和結構初始化中更詳細地描述初始化

訪問屬性

您可以訪問使用實例的屬性點語法。在點語法,你實例名稱后立即寫入屬性名,用句點(分離.),沒有任何空格:

print("The width of someResolution is\(someResolution.width)")

// Prints "The width of someResolution is 0"

在這個例子中,someResolution.width是指width的屬性someResolution,并返回其默認初始值0。

您可以深入到子屬性,如width在屬性resolution的屬性VideoMode:

print("The width of someVideoMode is\(someVideoMode.resolution.width)")

// Prints "The width of someVideoMode is 0"

您還可以使用點語法到一個新的值賦給變量屬性:

someVideoMode.resolution.width=1280

print("The width of someVideoMode is now\(someVideoMode.resolution.width)")

// Prints "The width of someVideoMode is now 1280"

注意

不同的Objective-C,斯威夫特使您能夠直接設置的結構屬性的子屬性。在上面的例子,把width該財產resolution的財產someVideoMode被直接設置,沒有你需要將整個設置resolution屬性為一個新值。

按成員初始化器的結構類型

所有的結構具有自動生成的成員逐一初始化,您可以用它來初始化新的結構實例的成員屬性。新實例的屬性的初始值可以被傳遞到由名成員逐一初始化:

letvga=Resolution(width:640,height:480)

不同的結構,類實例沒有收到默認成員逐一初始化。初始化中更詳細地描述初始化

結構和枚舉是值類型

一個值類型是一個類型,其值被復制時,它被分配給一個變量或常數,或當它被傳遞給函數。

你已經使用值類型廣泛的整個前幾章實際上是。事實上,所有斯威夫特 - 整數基本類型,浮點數,布爾值,字符串,數組和字典,是值類型,并作為幕后結構實現的。

所有的結構和枚舉是斯威夫特值類型。這意味著用戶可創建和任何結構和枚舉實例的任何值類型它們作為屬性,是當他們在你的代碼中傳來傳去始終復制。

考慮下面這個例子,它使用了Resolution前面例子中的結構:

lethd=Resolution(width:1920,height:1080)

varcinema=hd

這個例子聲明了一個名為常量hd并將其設置為一個Resolution與(全高清視頻的寬度和高度初始化實例,1920通過像素寬1080像素高)。

然后,它聲明了一個變量cinema并將其設置為當前值hd。因為Resolution是一個結構,一個復制現有實例而成,而這個新的拷貝被分配到cinema。即使hd與cinema現在具有相同的寬度和高度,它們是在幕后兩個完全不同的實例。

接下來,width財產cinema被修訂為稍微增多的2K標準用于數字電影放映(寬度2048像素寬,1080像素高):

cinema.width=2048

檢查width的屬性cinema表明,它確實已經更改為2048:

print("cinema is now\(cinema.width)pixels wide")

// Prints "cinema is now 2048 pixels wide"

然而,width與原始屬性hd實例仍具有的舊值1920:

print("hd is still\(hd.width)pixels wide")

// Prints "hd is still 1920 pixels wide"

當cinema被賦予的當前值hd,該存儲在hd被復制到新的cinema實例。最終的結果是兩個完全獨立的情況下,這正好包含相同的數值。因為它們是獨立的情況下,設置的寬度cinema以2048不影響存儲在寬度hd。

同樣的行為適用于枚舉:

enumCompassPoint{

casenorth,south,east,west

}

varcurrentDirection=CompassPoint.west

letrememberedDirection=currentDirection

currentDirection= .east

ifrememberedDirection== .west{

print("The remembered direction is still .west")

}

// Prints "The remembered direction is still .west"

當rememberedDirection被分配的值currentDirection,它實際上是設置為該值的副本。改變的值currentDirection此后不會影響被存儲在所述原始值的副本rememberedDirection。

類引用類型

不像值類型,引用類型當它們被分配給一個變量或常數,或當它們被傳遞給函數復制。而不是一個拷貝,為相同的現有實例的引用來替代。

下面是一個例子,使用VideoMode上面定義的類:

lettenEighty=VideoMode()

tenEighty.resolution=hd

tenEighty.interlaced=true

tenEighty.name="1080i"

tenEighty.frameRate=25.0

這個例子聲明一個稱為新的常數tenEighty,并將它以引用的新實例VideoMode的類。視頻模式分配的高清分辨率的副本,1920通過1080從之前。它被設置為交錯,并且被賦予的名稱"1080i"。最后,它被設置為幀速率25.0每秒幀。

接著,tenEighty被分配給一個新的常數,稱為alsoTenEighty和的幀速率alsoTenEighty被修改:

letalsoTenEighty=tenEighty

alsoTenEighty.frameRate=30.0

由于類是引用類型,tenEighty而alsoTenEighty實際上指的是同一個VideoMode實例。有效地,它們只是兩個用于同單個實例不同的名字。

檢查frameRate的財產tenEighty,它可以正確地報告的新的幀速率顯示30.0從底層的VideoMode實例:

print("The frameRate property of tenEighty is now\(tenEighty.frameRate)")

// Prints "The frameRate property of tenEighty is now 30.0"

請注意,tenEighty并alsoTenEighty聲明為常量,而不是變量。但是,你仍然可以改變tenEighty.frameRate和alsoTenEighty.frameRate由于價值觀tenEighty和alsoTenEighty常量本身并不真正改變,tenEighty而alsoTenEighty本身并沒有“商店”的VideoMode實例相反,他們都到VideoMode幕后實例。它是frameRate在底層的屬性VideoMode被改變,為了使恒定引用不值VideoMode。

運營商身份

因為類是參考的類型,它有可能為多個常量和變量來指幕后一類的相同的單一實例。(同樣是不適合的結構和枚舉真實的,因為當他們被分配到固定或可變他們總是復制或傳遞給函數)。

如果兩個常量或變量指的正是一個類的同一個實例它有時是有用的找出來。為了實現這一目標,雨燕提供了兩個身份運營商:

等同于(===)

不相同(!==)

使用這些運算符檢查兩個常量或變量是否指的是同一個實例:

iftenEighty===alsoTenEighty{

print("tenEighty and alsoTenEighty refer to the same VideoMode instance.")

}

// Prints "tenEighty and alsoTenEighty refer to the same VideoMode instance."

請注意,“相同”(代表由三個等號,或===)并不意味著同樣的事情為“等于”(由兩個代表等號,或==):

“等同于”是指兩個常數或類類型的的變量是指完全相同的類的實例。

“等于”是指兩個實例被認為是值“等于”或“等價物”,對于“平等”的一些適當的意義,由該類型的設計師定義。

當你定義自己的自定義類和結構,它是你的責任,決定為兩個實例是“平等”什么資格。定義你自己的實現的過程“等于”和“不等于”運營商在描述對等運營商

指針

如果你有C,C ++或Objective-C的經驗,你可能知道,這些語言使用指針指到的地址在內存中。這是指一些參考類型的實例迅速常量或變量是類似于C的指針,而不是直接指向內存中的地址,并且不需要你寫一個星號(*),以表明您創建參考。相反,這些參考文獻中定義像夫特任何其它固定或可變。

選擇類和結構之間

您可以同時使用類和結構來定義自定義數據類型作為您的程序代碼積木使用。

然而,結構實例總是被傳遞價值,和類實例總是過去了參考。這意味著它們適合于不同類型的任務。當你認為你需要一個項目中的數據結構和功能,決定每一個數據結構是否應該被定義為類或結構。

作為一般原則,考慮創建一個結構,當一個或多個條件適用:

結構的主要目的是封裝幾個比較簡單的數據值。

這是合理的預期,封裝的值將被復制,而不是當你分配或繞過該結構的一個實例引用。

由結構存儲的任何屬性本身的值類型,這也將被預期要復制的,而不是被引用。

該結構不需要從其他現有類型繼承屬性或行為。

良好候選結構的實例包括:

幾何形狀的尺寸,或者包封width屬性和height屬性,兩個類型的Double。

一種方法來指代范圍內的系列中,也許一個封裝start屬性和length特性,既類型Int。

在三維坐標系中,A點也許封裝x,y和z特性,每種類型的Double。

在其他情況下,定義一個類,并創建一個類的實例來進行管理,并通過引用傳遞。在實踐中,這意味著大多數自定義數據結構應該是類,而不是結構。

技術逼寫了那么多代碼,一會這個值變了,一會這個值又沒變,像變戲法一樣... ...

===========================================================================

無腦碼農看這里 ?:

之前百度了各種文章,各種舉例,代碼,論證,最后無奈看了官方文檔,2個小時后我終于理解了!

如圖:

ZN 類的實例化之間存在地址傳遞的關系,結構體的實例化之間是值傳遞的關系!

其實就是兩句話:

1 類的每個實例化之間存在地址傳遞的關系,(上邊例子地址同為:0x0000610000038140)在使用類時需要考慮繼承關系.

2 結構體的每個實例化之間是值傳遞的關系,賦給什么值,就是什么值.是相對獨立的關系.


最后總結:

? ? ? swift 3.0中 結構體比以前范圍更強大了,可以和類一樣有方法,擴展,屬性變異修飾還增加了下標法.但是重要的,結構體強調了每一個實例化之間獨立的存在,互不干涉的特點.

? ? ? 考慮到新增的上述特性,種種跡象表明,結構體是蘋果主要針對未來的Web服務器開發,科學計算,人工智能,等數值計算方面,量身定做的一個特性類型.喜歡這個領域的碼農們可以在結構體章節進行深入的研究.他對你來說比Class類型更加重要.

? ? ? ?如果只在IOS領域開發大眾化的APP方面,那結構體的新特性和我們的關系并不是很大.但是長遠來看,swift這門語言已經具備了目前所有語言的優點,就語言自身來說超越了PHP,Python,JAVA當前主流的語言,也包括Lisp函數式的很多優點.盡管如此swift為了兼容OC也還是做出了很多妥協.因此我們完全有理由認真學習swift的每一項特性,我完全相信,如同蘋果說的那樣,在未來20年之內swift將會是非常主流的語言!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容