Swift4類和結構(二)
屬性
定義
使用var
和let
定義
懶載入屬性
懶載入屬性是在首次用到的時候才載入,需要在宣告前標註lazy
修飾語來標明一個懶載入屬性。
懶載入屬性只能宣告為變數(也就是使用
var
定義)
當屬性載入需要耗費很長時間的時候,使用懶載入就很有意義了。
class DataImporter {
/*
DataImporter 是從外部檔案匯入資料的類,該類的初始化需要很長時間。
*/
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")
// 此時DataManager的例項裡的importer屬性還沒有建立
因為它被 lazy 修飾符所標記,只有在 importer 屬性第一次被訪問時才會建立 DataManager 例項,比如當查詢它的fileName 屬性時:
print(manager.importer.fileName)
注意:如果被標記為 lazy 修飾符的屬性同時被多個執行緒訪問並且屬性還沒有被初始化,則無法保證屬性只初始化一次。
計算屬性
在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)
print("square.origin is now at (\(square.origin.x), \(square.origin.y))")
// prints "square.origin is now at (10.0, 10.0)"
簡寫setter宣告
如果計算屬性的setter沒有為將要設定的值定義一個名字,預設使用newValue
。
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而沒有setter的屬性被稱為只讀屬性。
你可以通過去掉 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)
print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
// prints "the volume of fourByFiveByTwo is 40.0"
屬性觀察者
類似資料庫的觸發器
-
willSet
:屬性被儲存之前呼叫 -
didSet
:屬性被儲存之後呼叫
如果你實現了一個 willSet
觀察者,新的屬性值會以常量形式引數傳遞。你可以在你的 willSet
實現中為這個引數定義名字。如果你沒有為它命名,那麼它會使用預設的名字 newValue
。
同樣,如果你實現了一個 didSet
觀察者,一個包含舊屬性值的常量形式引數將會被傳遞。你可以為它命名,也可以使用預設的形式引數名 oldValue
。如果你在屬性自己的 didSet
觀察者裡給自己賦值,你賦值的新值就會取代剛剛設定的值.
class StepCounter {
var totalSteps: Int = 0 {
willSet(newTotalSteps) {
print("About to set totalSteps to \(newTotalSteps)")
}
didSet {
if totalSteps > oldValue {
print("Added \(totalSteps - oldValue) steps")
}
}
}
}
方法
在例項方法中修改值型別
結構和列舉是值型別。預設情況下,結構和列舉裡的方法是不能修改自身的屬性的。
如果需要在結構和列舉裡使用自身的方法改變屬性的值,可以在方法前加上mutating
關鍵字:
struct Point {
var x = 0.0, y = 0.0
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
x += deltaX
y += deltaY
}
}
型別方法
類似於其他語言中的類方法
- 宣告結構體和列舉的型別方法使用關鍵字
static
- 宣告類的型別方法使用關鍵字
class
class SomeClass {
class func someTypeMethod() {
// type method implementation goes here
}
}
SomeClass.someTypeMethod()
下標
Swift的類,結構和列舉可以過載下標運算。
你可以為一個型別定義多個下標,並且下標會基於傳入的索引值的型別選擇合適的下標過載使用。下標沒有限制單個維度,你可以使用多個輸入形參來定義下標以滿足自定義型別的需求。
下標語法
使用關鍵字subscript
定義下標運算,可以設定getter和setter方法讀寫下標,也可以設定只讀屬性。
// 下標可讀寫
subscript(index: Int) -> Int {
get {
// return an appropriate subscript value here
}
set(newValue) {
// perform a suitable setting action here
}
}
// 只讀
subscript(index: Int) -> Int {
// return an appropriate subscript value here
}
下標選項
下標可以接收任意數量的輸入形式引數,並且這些輸入形式引數可以是任意型別。下標也可以返回任意型別。
類或結構體可以根據自身需要提供多個下標實現,合適被使用的下標會基於值型別或者使用下標時下標方括號裡包含的值來推斷。這個對多下標的定義就是所謂的下標過載。
例子定義一個矩陣結構
struct Matrix {
let rows: Int, columns: Int
var grid: [Double]
init(rows: Int, columns: Int) {
self.rows = rows
self.columns = columns
grid = Array(repeating: 0.0, count: rows * columns)
}
func indexIsValid(row: Int, column: Int) -> Bool {
return row >= 0 && row < rows && column >= 0 && column < columns
}
subscript(row: Int, column: Int) -> Double {
get {
assert(indexIsValid(row: row, column: column), "Index out of range")
return grid[(row * columns) + column]
}
set {
assert(indexIsValid(row: row, column: column), "Index out of range")
grid[(row * columns) + column] = newValue
}
}
}
繼承
swift的繼承語法
class SomeSubclass: SomeSuperclass {
// subclass definition goes here
}
重寫
重寫必須新增關鍵字override
否則會編譯錯誤
// 重寫方法
class Train: Vehicle {
override func makeNoise() {
print("Choo Choo")
}
}
// 重寫屬性
class Car: Vehicle {
var gear = 1
override var description: String {
return super.description + " in gear \(gear)"
}
}
Super
使用super
呼叫父類屬性或者方法
阻止重寫
使用final
關鍵字
相關文章
- 類和結構
- golang類和結構體Golang結構體
- 《Effective C++》閱讀總結(二):類的構造、析構和賦值C++賦值
- Swift-類和結構體Swift結構體
- swift物件導向特性——類和結構體Swift物件結構體
- 類檔案結構_class類檔案的的結構
- swift4 kvcSwift
- JVM(筆記)—— Class 類檔案結構的說明(二)JVM筆記
- oracle,db2,mysql類比之二體系結構OracleDB2MySql
- Fastlane(二):結構AST
- 資料結構二之棧和佇列資料結構佇列
- 第二章:介面和目錄結構
- 類與結構體結構體
- 【Java】類的結構Java
- c#中結構體和類的比較C#結構體
- 【深入Java虛擬機器】之二:Class類檔案結構Java虛擬機
- 學習筆記:InnoDB表和索引結構(二)筆記索引
- RabbitMQ 入門(二)基本結構和訊息模型MQ模型
- PE結構分析(二)
- Swift4如何掃描二維碼瞭解一下Swift
- Spark構建聚類模型(二)Spark聚類模型
- C#中類和結構的一個區別...C#
- Swift 類與結構體Swift結構體
- OC中類的結構
- Swift,結構體與類Swift結構體
- Class類檔案結構
- 集合框架類結構圖框架
- 資料結構和演算法:二叉樹資料結構演算法二叉樹
- MATLAB(3)資料型別二(結構體和…Matlab資料型別結構體
- swift4 常用屬性Swift
- 第五章——結構體與類(實體和值)結構體
- 結構體和類中屬性定義需要static地方結構體
- [C++]類和物件(二)C++物件
- 二、FFmpeg的模組結構
- 結構體案例二:英雄結構體
- 資料結構:樹和二叉樹定義和術語資料結構二叉樹
- Python(二):選擇結構與迴圈結構Python
- iOS探索 類的結構分析iOS