Swift-屬性

存儲屬性

在其最簡單的形式中,存儲屬性是作為特定類或結(jié)構(gòu)的實例的一部分存儲的常量或變量。 存儲的屬性可以是變量存儲屬性(由var關(guān)鍵字引入)或常量存儲屬性(由關(guān)鍵字引入)柠掂。

您可以為存儲屬性提供默認值肝谭,作為其定義的一部分黔姜,如默認屬性值中所述俄占。 您還可以在初始化期間設(shè)置和修改存儲屬性的初始值腔长。 即使對于常量存儲的屬性也是如此辐烂,如在初始化期間分配常量屬性中所述遏插。

下面的示例定義了一個稱為FixedLengthRange的結(jié)構(gòu),它描述了一系列整數(shù)纠修,其范圍長度在創(chuàng)建后無法更改:

struct FixedLengthRange {
    var firstValue: Int
    let length: Int
}
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
// the range represents integer values 0, 1, and 2
rangeOfThreeItems.firstValue = 6
// the range now represents integer values 6, 7, and 8

FixedLengthRange的實例具有稱為firstValue的變量存儲屬性和稱為length的常量存儲屬性胳嘲。 在上面的示例中,長度在創(chuàng)建新范圍時初始化扣草,并且之后無法更改了牛,因為它是常量屬性颜屠。

常量結(jié)構(gòu)實例的存儲屬性

如果創(chuàng)建結(jié)構(gòu)的實例并將該實例分配給常量,那么即使它們被聲明為變量屬性鹰祸,也不能修改實例的屬性:

let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
// this range represents integer values 0, 1, 2, and 3
rangeOfFourItems.firstValue = 6
// this will report an error, even though firstValue is a variable property

因為rangeOfFourItems被聲明為一個常量(使用let關(guān)鍵字)甫窟,所以不可能改變它的firstValue屬性,即使firstValue是一個變量屬性蛙婴。

這種行為是由于結(jié)構(gòu)是值類型粗井。 當值類型的實例被標記為常量時,其所有屬性也是如此街图。

對于作為引用類型的類則不是這樣浇衬。 如果將引用類型的實例指定給常量,則仍然可以更改該實例的變量屬性餐济。

延遲存儲屬性

延遲存儲屬性是一種屬性耘擂,其初始值不會在第一次使用時計算。 你通過在聲明之前寫入lazy修飾符來指示一個惰性存儲屬性絮姆。

注意:
您必須始終將lazy屬性聲明為變量(使用var關(guān)鍵字)醉冤,因為它的初始值可能無法在實例初始化完成后檢索。 常量屬性在初始化完成之前必須始終具有值滚朵,因此不能聲明為延遲冤灾。

下面的示例使用延遲存儲屬性,以避免不必要的復雜類的初始化辕近。 此示例定義了兩個名為DataImporter和DataManager的類韵吨,這兩個類都不完整顯示:

class DataImporter {
    /*
     DataImporter is a class to import data from an external file.
     The class is assumed to take a non-trivial amount of time to initialize.
     */
    var fileName = "data.txt"
    // the DataImporter class would provide data importing functionality here
}

class DataManager {
    lazy var importer = DataImporter()
    var data = [String]()
    // the DataManager class would provide data management functionality here
}

let manager = DataManager()
manager.data.append("Some data")
manager.data.append("Some more data")
// the DataImporter instance for the importer property has not yet been created

因為它用lazy修飾符標記,所以只有在首次訪問importer屬性時才會創(chuàng)建importer屬性的DataImporter實例移宅,例如查詢其fileName屬性時:

print(manager.importer.fileName)
// the DataImporter instance for the importer property has now been created
// Prints "data.txt"

如果標記有l(wèi)azy修飾符的屬性由多個線程同時訪問归粉,并且該屬性尚未初始化,則不能保證該屬性只被初始化一次漏峰。

存儲屬性和實例變量

如果你有Objective-C的經(jīng)驗糠悼,你可能知道它提供了兩種方法來存儲值和引用作為類實例的一部分。 除了屬性浅乔,您可以使用實例變量作為存儲在屬性中的值的后備存儲倔喂。

Swift將這些概念統(tǒng)一到單個屬性聲明中。 Swift屬性沒有對應的實例變量靖苇,并且不直接訪問屬性的后備存儲席噩。 這種方法避免了對在不同上下文中如何訪問值的混淆,并將屬性的聲明簡化為單個確定的語句贤壁。 有關(guān)屬性的所有信息(包括其名稱悼枢,類型和內(nèi)存管理特性)在單個位置中定義為類型定義的一部分。

計算屬性

除了存儲的屬性脾拆,類馒索,結(jié)構(gòu)和枚舉可以定義計算屬性莹妒,實際上不存儲值。 相反绰上,它們提供了一個getter和一個可選的setter來檢索和間接設(shè)置其他屬性和值旨怠。

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))")
// Prints "square.origin is now at (10.0, 10.0)"

速記組合聲明

如果計算屬性的setter未定義要設(shè)置的新值的名稱,則使用缺省名稱newValue渔期。 這里有一個替代版本的Rect結(jié)構(gòu)运吓,它利用了這個簡寫符號:

struct AlternativeRect {
    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 {
            origin.x = newValue.x - (size.width / 2)
            origin.y = newValue.y - (size.height / 2)
        }
    }
}

只讀計算屬性

具有g(shù)etter但沒有setter的計算屬性稱為只讀計算屬性。 只讀計算屬性始終返回一個值疯趟,可以通過點語法訪問拘哨,但不能設(shè)置為其他值。

注意:
您必須使用var關(guān)鍵字聲明計算屬性(包括只讀計算屬性)作為變量屬性信峻,因為它們的值不是固定的倦青。 let關(guān)鍵字僅用于常量屬性,表示一旦將它們的值設(shè)置為實例初始化的一部分盹舞,它們的值就無法更改产镐。

您可以通過刪除get關(guān)鍵字及其大括號來簡化只讀計算屬性的聲明:

struct Cuboid {
    var width = 0.0, height = 0.0, depth = 0.0
    var volume: Double {
        return width * height * depth
    }
}
let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)
print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
// Prints "the volume of fourByFiveByTwo is 40.0"

屬性觀察者

屬性觀察者觀察并響應屬性值的變化。 每次設(shè)置屬性的值時踢步,都會調(diào)用屬性觀察器癣亚,即使新值與屬性的當前值相同。

您可以將屬性觀察器添加到您定義的任何存儲的屬性获印,lazy存儲屬性除外述雾。 您還可以通過覆蓋子類中的屬性,將屬性觀察器添加到任何繼承的屬性(無論是存儲還是計算)兼丰。 您不需要為未覆蓋的計算屬性定義屬性觀察器玻孟,因為您可以在計算屬性的setter中觀察并響應對其值的更改。 屬性覆蓋在覆蓋中描述鳍征。

您可以選擇在屬性上定義這兩個觀察者之一:

  • willSet在值被存儲之前被調(diào)用黍翎。
  • didSet在存儲新值之后立即調(diào)用。

如果你實現(xiàn)一個willSet觀察者艳丛,它作為一個常量參數(shù)傳遞新的屬性值匣掸。 您可以為此參數(shù)指定名稱,作為您的willSet實現(xiàn)的一部分氮双。 如果不在實現(xiàn)中寫入?yún)?shù)名稱和括號旺聚,那么該參數(shù)的缺省參數(shù)名稱為newValue。

類似地眶蕉,如果你實現(xiàn)一個didSet觀察者,它傳遞一個常量參數(shù)包含舊的屬性值唧躲。 您可以命名參數(shù)或使用默認參數(shù)名稱oldValue造挽。 如果您為自己的didSet觀察器中的屬性賦值碱璃,則您分配的新值將替換剛剛設(shè)置的值。

class StepCounter {
    var totalSteps: Int = 0 {
        willSet(newTotalSteps) {
            print("About to set totalSteps to \(newTotalSteps)")
        }
        didSet {
            if totalSteps > oldValue  {
                print("Added \(totalSteps - oldValue) steps")
            }
        }
    }
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
// About to set totalSteps to 200
// Added 200 steps
stepCounter.totalSteps = 360
// About to set totalSteps to 360
// Added 160 steps
stepCounter.totalSteps = 896
// About to set totalSteps to 896
// Added 536 steps

注意:
如果將一個具有觀察者的屬性作為一個in-out參數(shù)傳遞給一個函數(shù)饭入,willSet和didSet觀察者總是被調(diào)用嵌器。 這是因為用于輸入輸出參數(shù)的復制輸入輸出存儲器模型:該值始終寫回函數(shù)結(jié)尾處的屬性。 有關(guān)輸入 - 輸出參數(shù)行為的詳細討論谐丢,請參閱輸入 - 輸出參數(shù)爽航。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市乾忱,隨后出現(xiàn)的幾起案子讥珍,更是在濱河造成了極大的恐慌,老刑警劉巖窄瘟,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件衷佃,死亡現(xiàn)場離奇詭異,居然都是意外死亡蹄葱,警方通過查閱死者的電腦和手機氏义,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來图云,“玉大人惯悠,你說我怎么就攤上這事】⒖觯” “怎么了克婶?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長帕翻。 經(jīng)常有香客問我鸠补,道長,這世上最難降的妖魔是什么嘀掸? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任紫岩,我火速辦了婚禮,結(jié)果婚禮上睬塌,老公的妹妹穿的比我還像新娘泉蝌。我一直安慰自己,他們只是感情好揩晴,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布勋陪。 她就那樣靜靜地躺著,像睡著了一般硫兰。 火紅的嫁衣襯著肌膚如雪诅愚。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天劫映,我揣著相機與錄音违孝,去河邊找鬼刹前。 笑死,一個胖子當著我的面吹牛雌桑,可吹牛的內(nèi)容都是我干的喇喉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼校坑,長吁一口氣:“原來是場噩夢啊……” “哼拣技!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起耍目,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤膏斤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后制妄,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體掸绞,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年耕捞,在試婚紗的時候發(fā)現(xiàn)自己被綠了衔掸。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡俺抽,死狀恐怖敞映,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情磷斧,我是刑警寧澤振愿,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站弛饭,受9級特大地震影響冕末,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜侣颂,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一档桃、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧憔晒,春花似錦藻肄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至从撼,卻和暖如春州弟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工呆馁, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留桐经,地道東北人。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓浙滤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親气堕。 傳聞我的和親對象是個殘疾皇子纺腊,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 屬性將值跟特定的類、結(jié)構(gòu)或枚舉關(guān)聯(lián)茎芭。存儲屬性存儲常量或變量作為實例的一部分揖膜,而計算屬性計算(不是存儲)一個值。計算...
    窮人家的孩紙閱讀 414評論 0 0
  • Swift語法基礎(chǔ)(五)-- (類和結(jié)構(gòu)體趁仙、屬性、方法) 本章將會介紹 類和結(jié)構(gòu)體對比結(jié)構(gòu)體和枚舉是值類型類是引用...
    寒橋閱讀 1,081評論 0 1
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理垦页,服務(wù)發(fā)現(xiàn)雀费,斷路器,智...
    卡卡羅2017閱讀 134,657評論 18 139
  • Swift 屬性將值跟特定的類痊焊、結(jié)構(gòu)或枚舉關(guān)聯(lián)盏袄。 屬性可分為存儲屬性和計算屬性: 存儲屬性 計算屬性 存儲常量或變...
    零度_不結(jié)冰閱讀 400評論 0 0
  • 1.主動推進項目 對于自己負責的事情一定要積極主動推進,如果讓對接人一再催促薄啥,不僅是對工作進度的影響辕羽,也是會給其他...
    小萬管家閱讀 6,228評論 0 1