一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Swift - Swift教程之屬性詳解

Swift教程之屬性詳解

2020-12-19 15:37Swift教程網 Swift

這篇文章主要介紹了Swift教程之屬性詳解,屬性是描述特定類、結構或者枚舉的值,計算屬性存在于類、結構與枚舉中,存儲屬性僅僅只在類與結構中,需要的朋友可以參考下

屬性是描述特定類、結構或者枚舉的值。存儲屬性作為實例的一部分存儲常量與變量的值,而計算屬性計算他們的值(不只是存儲)。計算屬性存在于類、結構與枚舉中。存儲屬性僅僅只在類與結構中。

屬性通常與特定類型實例聯系在一起。但屬性也可以與類型本身聯系在一起,這樣的屬性稱之為類型屬性。

另外,可以定義屬性觀察者來處理屬性值發生改變的情況,這樣你就可以對用戶操作做出反應。屬性觀察者可以被加在自己定義的存儲屬性之上,也可以在從父類繼承的子類屬性之上。

1、存儲屬性

最簡單的情形,作為特定類或結構實例的一部分,存儲屬性存儲著常量或者變量的值。存儲屬性可分為變量存儲屬性(關鍵字var描述)和常量存儲屬性(關鍵字let描述)。

當定義存儲屬性時,你可以提供一個默認值,這些在“默認屬性值”描述。在初始化過程中你也可以設置或改變存儲屬性的初值。這個準則對常量存儲屬性也同樣適用(在“初始化過程中改變常量屬性”描述)

下面的例子定義了一個叫FixedLengthRange的結構,它描述了一個一定范圍內的整數值,當創建這個結構時,范圍長度是不可以被改變的:

復制代碼 代碼如下:

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的常量存儲屬性。以上的例子中,當范圍確定,length被初始化之后它的值是不可以被改變的

常量結構實例的存儲屬性
如果你創建一個結構實例,并將其賦給一個常量,這個實例中的屬性將不可以被改變,即使他們被聲明為變量屬性

 

復制代碼 代碼如下:
 
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 thought firstValue is a variable property

 

因為rangeOfFourItems是一個常量(let),即便firstValue是一個變量屬性,它的值也是不可以被改變的

這樣的特性是因為結構是值類型。當一個值類型實例作為常量而存在,它的所有屬性也作為常量而存在。

而這個特性對類并不適用,因為類是引用類型。如果你將引用類型的實例賦值給常量,依然能夠改變實例的變量屬性。

Lazy Stored Properties(懶惰存儲屬性?)

懶惰存儲屬性是當它第一次被使用時才進行初值計算。通過在屬性聲明前加上@lazy來標識一個懶惰存儲屬性。

注意

必須聲明懶惰存儲屬性為變量屬性(通過var),因為它的初始值直到實例初始化完成之后才被檢索。常量屬性在實例初始化完成之前就應該被賦值,因此常量屬性不能夠被聲明為懶惰存儲屬性。

當屬性初始值因為外部原因,在實例初始化完成之前不能夠確定時,就要定義成懶惰存儲屬性。當屬性初始值需要復雜或高代價的設置,在它需要時才被賦值時,懶惰存儲屬性就派上用場了。

下面的例子使用懶惰存儲屬性來防止類中不必要的初始化操作。它定義了類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 += "Some data"
manager.data += "Some more data"
// the DataImporter instance for the importer property has not yet been created

 

類DataManager有一個稱為data的存儲屬性,它被初始化為一個空的String數組。雖然DataManager定義的其它部分并沒有寫出來,但可以看出DataManager的目的是管理String數據并為其提供訪問接口。

DataManager類的部分功能是從文件中引用數據。這個功能是由DataImporter類提供的,這個類需要一定的時間來初始化,因為它的實例需要打開文件并見內容讀到內存中。

因為DataManager實例可能并不需要立即管理從文件中引用的數據,所以在DataManager實例被創建時,并不需要馬上就創建一個新的DataImporter實例。這就使得當DataImporter實例在需要時才被創建理所當然起來。

因為被聲明為@lazy屬性,DataImporter的實例importer只有在當它在第一次被訪問時才被創建。例如它的fileName屬性需要被訪問時:

 

復制代碼 代碼如下:

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

 

存儲屬性與實例變量

如果你使用過Objective-C,你應該知道它提供兩種方式來存儲作為類實例一部分的值與引用。除了屬性,你可以使用實例變量作為屬性值的后備存儲

Swift使用一個單一屬性聲明來統一這些概念。一個Swift屬性沒有與之相符的實例變量,并且屬性的后備存儲也不能直接訪問。這防止了在不通上下文中訪問值的混淆,并且簡化屬性聲明成為一個單一的、最終的語句。關于屬性的所有信息-包含名稱、類型和內存管理等-作為類型定義的一部分而定義。

2、計算屬性

除了存儲屬性,類、結構和枚舉能夠定義計算屬性。計算屬性并不存儲值,它提供getter和可選的setter來間接地獲取和設置其它的屬性和值。

 

復制代碼 代碼如下:

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)
println("square.origin is now at (\(square.origin.x), \(square.origin.y))")
// prints "square.origin is now at (10.0, 10.0)"

 

這個例子定義了三個處理幾何圖形的結構:

Point包含一個(x,y)坐標
Size包含寬度width和高度height
Rect定義了一個長方形,包含原點和大小size
Rect結構包含一個稱之為center的計算屬性。Rect當前中心點的坐標可以通過origin和size屬性得來,所以并不需要顯式地存儲中心點的值。取而代之的是,Rect定義一個稱為center的計算屬性,它包含一個get和一個set方法,通過它們來操作長方形的中心點,就像它是一個真正的存儲屬性一樣。

例子中定義了一個名為square的Rect變量,它的中心點初始化為(0, 0),高度和寬度初始化為10,由以下圖形中的藍色正方形部分。

變量square的center屬性通過點操作符訪問,它會調用center的getter方法。不同于直接返回一個存在的值,getter方法要通過計算才能返回長方形的中心點的值(point)。以上的例子中,getter方法返回中心點(5,5)。

然后center屬性被設置成新的值(15,15),這樣就把這個正方形向右向上移動到了途中黃色部分所表示的新的位置。通過調用setter方法來設置center,改變origin中坐標x和y的值,將正方形移動到新的位置。

Swift教程之屬性詳解

setter聲明的簡略寫法

如果計算屬性的setter方法沒有將被設置的值定義一個名稱,將會默認地使用newValue這個名稱來代替。下面的例子采用了這樣一種特性,定義了Rect結構的新版本:

復制代碼 代碼如下:

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)
}
}
}

 

只讀計算屬性

只讀計算屬性只帶有一個getter方法,通過點操作符,可以放回屬性值,但是不能修改它的值。
注意
應該使用var關鍵字將計算屬性-包含只讀計算屬性-定義成變量屬性,因為它們的值并不是固定的。let關鍵字只被常量屬性說使用,以表明一旦被設置它們的值就是不可改變的了

通過移除get關鍵字和它的大括號,可以簡化只讀計算屬性的定義:

 

復制代碼 代碼如下:

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)
println("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
// prints "the volume of fourByFiveByTwo is 40.0

 

這個例子定義了一個三維長方體結構Cuboid,包含了長寬高三個屬性,和一個表示長方體容積的只讀計算屬性volume。volume值是不可被設置的,因為它直接由長寬高三個屬性計算而來。通過提供這樣一個只讀計算屬性,Cuboid使外部用戶能夠訪問到其當前的容積值。

3、屬性觀察者

屬性觀察者觀察屬性值的改變并對此做出響應。當設置屬性的值時,屬性觀察者就被調用,即使當新值同原值相同時也會被調用。

除了懶惰存儲屬性,你可以為任何存儲屬性加上屬性觀察者定義。另外,通過重寫子類屬性,也可以繼承屬性(存儲或計算)加上屬性觀察者定義。屬性重寫在“重寫”章節定義。

注意
不必為未重寫的計算屬性定義屬性觀察者,因為可以通過它的setter方法直接對值的改變做出響應

定義屬性的觀察者時,你可以單獨或同時使用下面的方法:
willSet:設置值前被調用
didSet:設置值后立刻被調用

當實現willSet觀察者時,新的屬性值作為常量參數被傳遞。你可以為這個參數起一個名字,如果不的話,這個參數就默認地被命名成newValue。

在實現didSet觀察者時也是一樣,只不過傳遞的產量參數表示的是舊的屬性值。

注意:
屬性初始化時,willset和didSet并不會被調用。只有在初始化上下文之外,當設置屬性值時才被調用

下面是一個willSet和didSet用法的實例。定義了一個類StepCounter,用來統計人走路時的步數。它可以從計步器或其它計數器上獲取輸入數據,對日常聯系鍛煉的步數進行追蹤。

 

復制代碼 代碼如下:

class StepCounter {
var totalSteps: Int = 0 {
willSet(newTotalSteps) {
println("About to set totalSteps to \(newTotalSteps)")
}
didSet {
if totalSteps > oldValue  {
println("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

 

類StepCounter聲明了一個Int類型的、含有willSet和didSet觀察者的存儲屬性totalSteps。當這個屬性被賦予新值時,willSet和didSet將會被調用,即使新值和舊值是相同的。

例子中的willSet觀察者為參數起了個新的名字newTotalSteps,它簡單地打印了即將被設置的值。

當totalSteps值被更新時,didSet觀察者被調用,它比較totalSteps的新值和舊值,如果新值比舊值大,就打印所增加的步數。didSet并沒有為舊值參數命名,在本例中,將會使用默認的名字oldValue來表示舊的值。

注意

如果通過didSet來設置屬性的值,即使屬性值剛剛被設置過,起作用的也將會是didSet,即新值是didSet設置的值

4、全局和局部變量

以上所寫的關于計算與觀察屬性值的特性同樣適用于全局和局部變量。全局變量是在任何函數、方法、閉包、類型上下文外部定義的變量,而局部變量是在函數、方法、閉包中定義的變量。

前面章節所遇到過的全局、局部變量都是存儲變量。和存儲屬性一樣,存儲變量為特定類型提供存儲空間并且可以被訪問

但是,你可以在全局或局部范圍定義計算變量和存儲變量觀察者。計算變量并不存儲值,只用來計算特定值,它的定義方式與計算屬性一樣。

注意
全局常量和變量通常是延遲計算的,跟懶惰存儲屬性一樣,但是不需要加上@lazy。而局部常量與變量不是延遲計算的。

5、類型屬性

實例屬性是特定類型實例的屬性。當創建一個類型的實例時,這個實例有自己的屬性值的集合,這將它與其它實例區分開來。

也可以定義屬于類型本身的屬性,即使創建再多的這個類的實例,這個屬性也不屬于任何一個,它只屬于類型本身,這樣的屬性就稱為類型屬性。

類型屬性適用于定義那些特定類型實例所通用的屬性,例如一個可以被所有實例使用的常量屬性(就像c中的靜態常量),或者變量屬性(c中的靜態變量)。

可以為值類型(結構、枚舉)定義存儲類型屬性和計算類型屬性。對類而言,只能夠定義計算類型屬性。

值類型的存儲類型屬性可以是常量也可以是變量。而計算類型屬性通常聲明成變量屬性,類似于計算實例屬性

注意
不想存儲實例屬性,你需要給存儲類型屬性一個初始值。因為類型本身在初始化時不能為存儲類型屬性設置值

類型屬性句法

在C和Objective-C中,定義靜態常量、變量和全局靜態變量一樣。但是在swift中,類型屬性的定義要放在類型定義中進行,在類型定義的大括號中,顯示地聲明它在類型中的作用域。

對值類型而言,定義類型屬性使用static關鍵字,而定義類類型的類型屬性使用class關鍵字。下面的例子展示了存儲和計算類型屬性的用法:

 

復制代碼 代碼如下:

struct SomeStructure {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
// return an Int value here
}
}
enum SomeEnumeration {
static var storedTypeProperty = "Some value."     static var computedTypeProperty: Int {     // return an Int value here
}
}
class SomeClass {
class var computedTypeProperty: Int {
// return an Int value here
}
}

 

注意

上面的例子是針對只讀計算類型屬性而言的,不過你也可以像計算實例屬性一樣定義可讀可寫的計算類型屬性

查詢與設置類型屬性

像實例屬性一樣,類型屬性通過點操作符來查詢與設置。但是類型屬性的查詢與設置是針對類型而言的,并不是針對類型的實例。例如:

 

復制代碼 代碼如下:

println(SomeClass.computedTypeProperty)
// prints "42"
println(SomeStructure.storedTypeProperty)
// prints "Some value."
SomeStructure.storedTypeProperty = "Another value."
println(SomeStructure.storedTypeProperty)
// prints "Another value.

 

下面的例子在一個結構中使用兩個存儲類型屬性來展示一組聲音通道的音頻等級表。每個通道使用0到10來表示聲音的等級。

從下面的圖表中可以看出,使用了兩組聲音通道來表示一個立體聲音頻等級表。當一個通道的等級為0時,所有的燈都不會亮,當等級為10時,所有的燈都會亮。下面的圖中,左邊的通道表示聲音等級為9,右邊的為7

Swift教程之屬性詳解

上述的聲音通道由以下的AudioChannel結構實例來表示:

 

復制代碼 代碼如下:

struct AudioChannel {
static let thresholdLevel = 10
static var maxInputLevelForAllChannels = 0
var currentLevel: Int = 0 {
didSet {
if currentLevel > AudioChannel.thresholdLevel {
//cap the new audio level to the threshold level
currentLevel = AudioChannel.thresholdLevel
}
if currentLevel > AudioChannel.maxInputLevelForAllChannels {
// store this as the new overall maximum input level
AudioChannel.maxInputLevelForAllChannels = currentLevel
}
}
}
}

 

AudioChannel結構定義了兩個存儲類型屬性。thresholdLevel定義了音頻所能達到的最高等級,對所有的AudoChannel實例而言,是個值為10的常量。當一個聲音信號的值超過10時,會被截斷為其閾值10。

第二個類型屬性是一個變量存儲屬性maxInputLevelForAllChannels。它保存了當前所有AudioChannel實例中所接受到聲音的最高等級,它被初始化為0。

結構還定義了一個存儲實例屬性currentLevel,表示當前的通道聲音等級。這個屬性使用didSet屬性觀察者來檢測currentLevel的改變。這個觀察者執行兩道檢查:

如果currentlevel的新值比閾值thresholdLevel大,currentLevel將被設置成thresholdLevel
如果currentLevel的新值比所有AudioChannel實例之前接受到的最大聲音等級還要大,那么maxInputLevelForAllChannles將會被設置成cueentLevel大值。

注意

第一道檢查中,didSet為currentLevel設置了新值。這并不會造成觀察者再次被調用

可以創建兩個AudioChannel實例,leftChannel和rightChannel,來表示一個立體聲系統:

復制代碼 代碼如下:

var leftChannel = AudioChannel()
var rightChannel = AudioChannel()


如果設置左通道的currentLevel為7,它的類型屬性maxInputLevelForAllChannels將更新成為7:

 

 

復制代碼 代碼如下:

leftChannel.currentLevel = 7
println(leftChannel.currentLevel)
// prints "7"
println(AudioChannel.maxInputLevelForAllChannels)
// prints "7”
 
如果像設置右通道的currentlevel為11,它的值將被截短成為10,而且maxInputLevelForAllChannels的值也將更新為10:
“rightChannel.currentLevel = 11
println(rightChannel.currentLevel)
// prints "10"
println(AudioChannel.maxInputLevelForAllChannels)
// prints "10"

延伸 · 閱讀

精彩推薦
  • Swiftswift where與匹配模式的實例詳解

    swift where與匹配模式的實例詳解

    這篇文章主要介紹了swift where與匹配模式的實例詳解的相關資料,這里附有簡單的示例代碼,講的比較清楚,需要的朋友可以參考下...

    追到夢的魔術師14382021-01-06
  • SwiftSwift能代替Objective-C嗎?

    Swift能代替Objective-C嗎?

    這是我在網上上看到的答案,復制粘貼過來和大家分享一下,因為我和很多人一樣很關心Swift的出現對Mac開發的影響和對Objective-C的影響。...

    Swift教程網4412020-12-16
  • Swiftmac git xcrun error active developer path 錯誤

    mac git xcrun error active developer path 錯誤

    本文主要是講訴了如何解決在mac下使用git;xcode4.6的環境時,出現了錯誤(mac git xcrun error active developer path)的解決辦法,希望對大家有所幫助...

    Swift教程網2232020-12-16
  • SwiftSwift中轉義閉包示例詳解

    Swift中轉義閉包示例詳解

    在Swift 中的閉包類似于結構塊,并可以在任何地方調用,下面這篇文章主要給大家介紹了關于Swift中轉義閉包的相關資料,需要的朋友可以參考下...

    小小小_小朋友11412021-12-26
  • SwiftSwift教程之基礎數據類型詳解

    Swift教程之基礎數據類型詳解

    這篇文章主要介紹了Swift教程之基礎數據類型詳解,本文詳細講解了Swift中的基本數據類型和基本語法,例如常量和變量、注釋、分號、整數、數值類型轉換等...

    Swift教程網5162020-12-18
  • SwiftSwift使用CollectionView實現廣告欄滑動效果

    Swift使用CollectionView實現廣告欄滑動效果

    這篇文章主要為大家詳細介紹了Swift使用CollectionView實現廣告欄滑動效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    Stevin的技術博客12372021-01-13
  • SwiftSwift的74個常用內置函數介紹

    Swift的74個常用內置函數介紹

    這篇文章主要介紹了Swift的74個常用內置函數介紹,這篇文章列舉出了所有的Swift庫函數,內置函數是指無需引入任何模塊即可以直接使用的函數,需要的朋友可...

    Swift教程網5802020-12-19
  • SwiftSwift實現多個TableView側滑與切換效果

    Swift實現多個TableView側滑與切換效果

    這篇文章主要為大家詳細介紹了Swift實現多個TableView側滑與切換效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    乞力馬扎羅的雪雪5822021-01-08
主站蜘蛛池模板: 国产亚洲精品美女2020久久 | 99精品99| 暖暖 免费 高清 日本 在线1 | 法国贵妇一级伦理hd | 無码一区中文字幕少妇熟女H | 日本免费久久久久久久网站 | 国产精品成人一区二区 | 免费黄色片网站 | 厨房高h | 亚洲精品无码不卡在线观看 | 午夜理论片YY4399影院 | 免费成年视频 | 无颜之月5集全免费看无删除 | 99年水嫩漂亮粉嫩在线播放 | 无限资源在线观看高清 | 国产精品一级片 | 韩剧消失的眼角膜免费完整版 | 亚洲香蕉网久久综合影院3p | 久青草国产在线观看视频 | 免费在线观看小视频 | 国产99re在线观看69热 | 午夜在线a亚洲v天堂网2019 | 五月婷婷在线免费观看 | 不卡一区二区三区 | 韩国靠逼 | 91大神第九部红酒气质女 | 男人天堂2023| 欧美男男gaysgays | 国产精品免费久久久久影院小说 | 精品亚洲永久免费精品 | 日韩欧美亚洲一区精选 | 韩剧hd| 强波多野结衣女教师 | 日韩一级片在线播放 | 国产亚洲精品自在线亚洲情侣 | 国产精品久久久久久久久 | 精品视频免费在线 | 欧美摸胸| 国产小嫩模好紧 | 国产精品成人免费 | 久久精品国产色蜜蜜麻豆国语版 |