・大文字のSelfについて
セルフキーワードにはSelfとselfがあるが、今回は、Selfについて利用方法を学ぶ
・Selfの利用方法
・型の内部での型自身へのアクセス
Selfは、型の内部での型自身へのアクセスを行うことができる。これにより、スタティックプロパティやスタティックメソッドへのアクセスが簡単になる。
以下の例では、printNum()メソッドで型自身に紐づくプロパティであるnumにアクセスしている。
そして、インスタンスプロパティであるstrにSelfでアクセスしようとするとエラーになります。これは、インスタンスプロパティが型のインスタンスに紐づくプロパティであり、型自身に紐づいていないためである。
struct someSelfProperty {
static let num : Int = 100
let str : String = "Hello"
func printNum() {
print(Self.num)
print(Self.str) // インスタンスプロパティにはアクセスできないためエラー
}
}
スタティックメソッドにおいても同じようにアクセスできる
struct someSelfMethod {
var num : Int
static func judge(inputNum: Int) -> Bool {
guard inputNum == 100 else {
return false
}
return true
}
func printJudge() {
print(Self.judge(inputNum: num))
}
}
次に、プロトコルにおけるSelfの利用方法について見ていく
・プロトコルでの利用
プロトコルでの利用方法は3つある
①protocol extensionを準拠する型で制限したい場合
protocol SomeProtocol {}
class SomeClass {}
// SomeClassを継承していれば参照可能
extension SomeProtocol where Self: SomeClass {
func someFunc() {
print("someFunc")
}
}
//SomeClassを継承しているためextensionで定義したインスタンスメソッドが参照可能
class SomeSubClass : SomeClass, SomeProtocol {}
let someSubClass = SomeSubClass()
someSubClass.someFunc() // "someFunc"
//SomeClassを継承していないためextensionで定義したインスタンスメソッドが参照不可能
class OtherSomeSubClass : SomeProtocol {}
let otherSumSubClass = OtherSomeSubClass()
otherSumSubClass.someFunc() //エラー
②protocol extensionを準拠する型のAssociatedType(連想型)で制限する場合
class SomeClass {}
protocol SomeProtcol {
associatedtype AssociatedType
}
// AssociatedTypeがSomeClassを継承していればこのインスタンスメソッドを参照できる
extension SomeProtcol where Self.AssociatedType : SomeClass {
func printJudge(_ str: String) -> Bool {
guard str == "Hello" else {
return false
}
return true
}
}
struct SomeStruct : SomeProtcol {
// SomeClassを継承しているためSomeProtocolのインスタンスメソッドを参照できる
typealias AssociatedType = SomeClass
}
let some = SomeStruct().printJudge("Hello") // "true"
struct OtherSomeStruct : SomeProtcol {
// StringではなくSomeClass型を継承しなければSomeProtocolのインスタンスメソッドは参照できない
typealias AssociatedType = String
}
let other = OtherSomeStruct().printJudge("Hello") //エラー
③プロトコルを定義する際にメソッドや戻り値の型に指定する場合
protocol SomeProtocol {
func someArgumentMethod(argument: Self) -> Void
func someReturnValueMethod() -> Self
}
・クラス内での利用
クラス内で定義したメソッドの戻り値の型の指定でのみ利用することができる。
class SomeClass {
func someMethod() -> Self {
return self
}
}
class SomeSubClass: SomeClass {
let name = "okadai"
}
let some = SomeSubClass().someMethod().name
print(some) // "okadai"