Swift學習筆記 十九 屬性

2021-09-25 23:44:15 字數 4434 閱讀 5772

屬性將值與特定的類、結構體或列舉關聯。儲存屬性會將常量和變量儲存為實例的一部分,⽽計算屬性則是直接計算(而不是存

儲)值。計算屬性可以用於類、結構體和列舉,⽽儲存屬性只能用於類和結構體。

儲存屬性和計算屬性通常與特定型別的實例關聯。但是,屬性也可以直接與型別本身關聯,這種屬性稱為型別屬性

另外,還可以定義屬性觀察器來監控屬性值的變化,以此來觸發自定義的操作。屬性觀察器可以新增到類本身定義的儲存屬性

上,也可以新增到從⽗類繼承的屬性上。

簡單來說,乙個儲存屬性就是儲存在特定類或結構體實例里的乙個常量或變量。儲存屬性可以是變量儲存屬性(用關鍵字var 定

義),也可以是常量儲存屬性(⽤關鍵字 let 定義)。

可以在定義儲存屬性的時候指定預設值,請參考預設構造器 一節。也可以在構造過程中設定或修改儲存屬性的值,甚⾄修改常量

儲存屬性的值(常量屬性沒有初始值的情況下),請參考《構造過程中常量屬性的修改》 一節。

下⾯的例子定義了乙個名為 fixedlengthrange 的結構體,該結構體用於描述整數區間,且這個範圍值在被建立後不能被修改。

struct fixedlengthrange

如果整個 getter 是單一表示式,getter 會隱式地返回這個表示式結果。下面是另乙個版本的 rect 結構體,用到了簡化的 getter

和 setter 宣告:

struct compactrect

在 getter 中忽略 return 與在函式中忽略 return 的規則相同,請參考《隱式返回的函式》。

只有 getter 沒有 setter 的計算屬性叫唯讀計算屬性。唯讀計算屬性總是返回乙個值,可以通過點運算子訪問,但不能設定新的

值。

必須使用 var 關鍵字定義計算屬性,包括唯讀計算屬性,因為它們的值不是固定的。 let 關鍵字只用來宣告常量屬性,表示初始

化後再也無法修改的值。

唯讀計算屬性的宣告可以去掉 get 關鍵字和花括號:

struct cuboid

let fourbyfivebytwo = cuboid(width: 4.0, height: 5.0, depth: 2.0)

print("the volume of fourbyfivebytwo is \(fourbyfivebytwo.volume)")

// 列印「the volume of fourbyfivebytwo is 40.0」

這個例子定義了乙個名為 cuboid 的結構體,表示三維空間的⽴方體,包含 width 、 height 和 depth 屬性。結構體還有乙個名為 

volume 的唯讀計算屬性用來返回⽴方體的體積。為 volume 提供 setter 毫⽆意義,因為無法確定如何修改 width 、 height 和 

depth 三者的值來匹配新的 volume 。然而, cuboid 提供乙個唯讀計算屬性來讓外部使用者直接獲取體積是很有用的。

注意這裡的 return 不能省略

屬性觀察器監控和響應屬性值的變化,每次屬性被設定值的時候都會呼叫屬性觀察器,即使新值和當前值相同的時候也不例外。

你可以為除了延時載入儲存屬性之外的其他儲存屬性新增屬性觀察器,你也可以在子類中通過重寫屬性的方式為繼承的屬性(包括

儲存屬性和計算屬性)新增屬性觀察器。你不必為非重寫的計算屬性新增屬性觀察器,因為你可以直接通過它的 setter 監控和響

應值的變化。屬性重寫請參考《重寫》。

可以為屬性新增其中乙個或兩個觀察器:

willset 在新的值被設定之前呼叫

didset 在新的值被設定之後呼叫

willset 觀察器會將新的屬性值作為常量引數傳入,在 willset 的實現**中可以為這個引數指定乙個名稱,如果不指定則引數仍

然可用,這時使用預設名稱 newvalue 表示。

同樣, didset 觀察器會將舊的屬性值作為引數傳⼊,可以為該引數指定乙個名稱或者使用預設引數名 oldvalue 。如果在

didset ⽅法中再次對該屬性賦值,那麼新值會覆蓋舊的值。

在父類初始化方法呼叫之後,在子類構造器中給父類的屬性賦值時,會呼叫父類屬性的 willset 和 didset 觀察器。而在父類初始

化方法呼叫之前,給子類的屬性賦值時不會調⽤子類屬性的觀察器。

有關構造器代理的更多資訊,請參考《值型別的構造器代理》和《類的構造器代理》。

下⾯是⼀個 willset 和 didset 實際運用的例子,其中定義了乙個名為 stepcounter 的類,⽤來統計乙個人步⾏時的總步數。這個

類可以跟計步器或其他日常鍛鍊的統計裝置的輸入資料配合使用。

class stepcounter

enum someenumeration

class someclass

if currentlevel > audiochannel.maxinputlevelforallchannels {

// 儲存當前⾳量作為新的最大輸入⾳量

audiochannel.maxinputlevelforallchannels = currentlevel

audiochannel 結構定義了 2 個儲存型型別屬性來實現上述功能。第乙個是 thresholdlevel ,表示⾳量的最大上限閾值,它是⼀

個值為 10 的常量,對所有實例都可見,如果⾳量高於 10 ,則取最大上限值 10 (⻅後面描述)。

第二個型別屬性是變量儲存型屬性 maxinputlevelforallchannels ,它用來表示所有 audiochannel 實例的最大輸入⾳量,初始值

是 0 。

audiochannel 也定義了乙個名為 currentlevel 的儲存型實例屬性,表示當前聲道現在的⾳量,取值為 0 到 10 。

屬性 currentlevel 包含 didset 屬性觀察器來檢查每次設定後的屬性值,它做如下兩個檢查:

如果 currentlevel 的新值大於允許的閾值 thresholdlevel ,屬性觀察器將 currentlevel 的值限定為閾值 thresholdlevel 。

如果修正後的 currentlevel 值大於靜態型別屬性 maxinputlevelforallchannels 的值,屬性觀察器就將新值儲存在 

maxinputlevelforallchannels 中。

在第乙個檢查過程中, didset 屬性觀察器將 currentlevel 設定成了不同的值,但這不會造成屬性觀察器被再次呼叫。可以使用

結構體 audiochannel 建立兩個聲道 leftchannel 和 rightchannel ,用以表示立體聲系統的⾳量:

var leftchannel = audiochannel()

var rightchannel = audiochannel()

如果將左聲道的 currentlevel 設定成 7 ,型別屬性 maxinputlevelforallchannels 也會更新成 7 :

leftchannel.currentlevel = 7

print(leftchannel.currentlevel)

// 輸出「7」

print(audiochannel.maxinputlevelforallchannels)

// 輸出「7」

如果試圖將右聲道的 currentlevel 設定成 11 ,它會被修正到最大值 10 ,同時 maxinputlevelforallchannels 的值也會更新到10:

rightchannel.currentlevel = 11print(rightchannel.currentlevel)

// 輸出「10」

print(audiochannel.maxinputlevelforallchannels)

// 輸出「10」

注意這章不停的說變數和屬性的關係,其實他們是從不同的角度來說的,屬性包括了變數和常量。

Swift學習筆記 屬性

定義乙個屬性 struct fixedlengthrange fixedlengthrange這個類裡面有兩個屬性,乙個為 firstvalue int 為可變型別,另外乙個為 length 為不可變型別 屬性賦值 var rangeofthreeitems fixedlengthrange fir...

Swift學習筆記 屬性

屬性分為儲存屬性與計算屬性,儲存屬性可以有預設值,計算屬性則根據已有資訊返回某種計算結果。類,結構體,列舉都可以有屬性 不使用 獲取值的屬性都是基本儲存屬性,包括讀寫屬性 var 宣告 以及唯讀屬性 let宣告 和巢狀函式一樣,型別也可以巢狀 class person 顏色 var color co...

Swift學習筆記 屬性

swift中屬性是描述特定類 結構或者列舉的值,可以分為以下幾種 1.儲存屬性 stored properties 2.計算屬性 computed properties 3.型別屬性 type properties 儲存屬性 儲存屬性就是例項物件的該屬性不需要自己額外實現方法,直接簡單明瞭 訪問原始...