📚 参考
-
プロトコル(Protocols) / The Swift Programming Language(日本語版)
→ Swiftの公式ドキュメントの日本語版 -
Swift Protocols: Properties distinction(get, get set)🏃🏻♀️🏃🏻
→ SwiftにおけるProtocolの{ get }
/{ get set }
について言及した記事
🔰 { get }
と{ get set }
の意味とその違い
プロパティ要件(Property Requirements)に記述する{ get }
・{ get set }
は、プロトコル型インスタンスに対するパーミッションであり、Computed Propertyの宣言時に記述するget {...}
やset {...}
とは無関係である
プロトコル型とは
protocol Animal {}
struct Dog: Animal {}
// ✅ プロトコル型インスタンス
let animal: Animal = Dog()
// ❎ プロトコル型インスタンスでない
let dog: Dog = Dog()
プロトコルの宣言
protocol Sample {
/**
{ get } .. プロトコル型インスタンスの場合は代入不可
{ get set } .. プロトコル型インスタンスの場合でも代入可能
*/
var get_constant: Int { get }
var get_variable: Int { get }
var get_computed: Int { get }
var get_private_set: Int { get }
var getset_variable: Int { get set }
var getset_computed: Int { get set }
}
プロトコルへの準拠(プロパティ要件)
struct SampleStructure: Sample {
let get_constant: Int
var get_variable: Int // ✅ storedでもcomputedでもよい
var get_computed: Int { // ✅ storedでもcomputedでもよい
get {
return secret
}
set { // ✅ プロパティ要件の{ get }とComputed Propertyの{ get set }は無関係
print("private variable 'secret' value has changed.")
secret = newValue
}
}
private(set) var get_private_set: Int
var getset_variable: Int
var getset_computed: Int {
get {
return secret
}
set {
print("private variable 'secret' value has changed.")
self.secret = newValue
}
}
// 説明用のPrivateプロパティ
private var secret: Int = -1
}
Swiftは、基本的にプロトコル型は自身のプロトコルに準拠していない(= self-conformance
をもたない)ものとする。
そうでないと、後述するParametric Polymorphism
においてはプロトコルのメンバが未定義動作を引き起こしてしまう。
Parametric Polymorphismによる未定義動作
func protocolTypeDoesNotConformProtocol<S: Sample>(_ sample: S) {
let num: Int = sample.get_constant // ⚠ sampleがSampleインスタンスの場合は未初期化のため、未定義動作になる
}
プロパティへの値の代入
struct SampleStructure: Sample {
init() {
get_constant = 0
get_variable = 0
get_computed = 0
get_private_set = 0
getset_variable = 0
getset_computed = 0
}
mutating func mutate() {
// get_constant = 1 ⛔ cannot assign to property: 'get_constant' is a 'let' constant
get_variable = 1
get_computed = 1
get_private_set = 1
getset_variable = 1
getset_computed = 1
}
}
// ✅ プロトコルに準拠したインスタンスからは{get}要件のプロパティに対して代入可能
var conformed: SampleStructure = SampleStructure()
// conformed.get_constant = 1 ⛔ cannot assign to property: 'get_constant' is a 'let' constant
conformed.get_variable = 1
conformed.get_computed = 1
// conformed.get_private_set = 1 ⛔ cannot assign to property: 'get_private_set' setter is inaccessible
conformed.getset_variable = 1
conformed.getset_computed = 1
// ❎ プロトコル型インスタンスからは{get}要件のプロパティに対して代入不可
var unconformed: Sample = SampleStructure()
// unconformed.get_constant = 1 ⛔ cannot assign to property: 'get_constant' is a get-only property
// unconformed.get_variable = 1 ⛔ cannot assign to property: 'get_variable' is a get-only property
// unconformed.get_computed = 1 ⛔ cannot assign to property: 'get_computed' is a get-only property
// unconformed.get_private_set = 1 ⛔ cannot assign to property: 'get_private_set' is a get-only property
unconformed.getset_variable = 1
unconformed.getset_computed = 1