バージョン
Xcode 11.3.1
Swift 5.1.3
方法
メソッドは、特定のタイプに関連付けられた関数です。
インスタンスメソッドは、特定のタイプのインスタンスの特定のタスクと関数をカプセル化します。タイプメソッドはタイプ自体に関連付けられています。タイプメソッドは、Objective-Cのクラスメソッドに似ています。
- Objective-Cでは、クラスはメソッドを定義できる唯一のタイプです。
- Swiftでは、型(クラス/構造/列挙型)のメソッドを定義できます。
インスタンスメソッド
インスタンスメソッドは、特定のクラス、構造、または列挙型のインスタンスに属するメソッドです。
インスタンスメソッドには、次の特徴があります。
- インスタンスのプロパティにアクセスして変更できます
- そのタイプの他のインスタンスメソッドにアクセスできます
- 属するタイプの前括弧(())と後括弧(())の間に書き込む必要があります
- 属するクラスの特定のインスタンスからのみ呼び出すことができます
class Counter {
var count = 0
func increment() {
count += 1
printSelf()
}
func increment(by amount: Int) {
count += amount
printSelf()
}
func reset() {
count = 0
printSelf()
}
func printSelf() {
print("count = \(count)")
}
}
let counter = Counter()
counter.increment()
counter.increment(by: 2)
counter.reset()
/**
count = 1
count = 3
count = 0
*/
上記の例では、プロパティ/メソッドにアクセスするために暗黙の呼び出しが使用されています。
自己属性
タイプの各インスタンスは、インスタンス自体に完全に同等である自己と呼ばれる暗黙の属性を持っています。あなたが現在のインスタンスを参照するインスタンスのインスタンスメソッドでは、この暗黙の自己属性を使用することができます。
それがに言われる理由上記の例は次のとおりです。暗黙の呼び出しは、暗黙の自己属性を使用するためです。
完全な表現(明示的な呼び出し)は次のとおりです。
func increment() {
self.count += 1
self.printSelf()
}
selfを省略できますが、場合によっては明示的な書き込みを使用する必要があります。
たとえば、上記の例で、メソッドincrement(by amount:Int)の量がcountに変更された場合、結果は私たちの結果とは異なります。パラメータカウントの優先度がストレージ属性カウントよりも大きいため、ストレージ属性カウントを計算
する必要があるため、selfを使用する必要があり、効果は同じです。
func increment(by count: Int) {
self.count += count
printSelf()
}
外部パラメータ名とローカルパラメータ名
前の関数の章では、パラメーターラベルとパラメーター名について説明しました。
この章では、メソッド呼び出しが含まれるため、パラメーターラベルを外部パラメーター名に変更し、パラメーター名をローカルパラメーター名に変更します
。Swift関数パラメーターローカル名(関数本体内で使用)と外部名(関数の呼び出し時に使用)を同時に指定します。
Objective-Cと同様に、Swiftのメソッドの名前は通常、前置詞を使用して、with、for、byなどのメソッドの最初のパラメーターを指します。
最初の例では、byは外部パラメーターの名前であり、amountはローカルパラメーターの名前です。
func increment(by amount: Int) {
count += amount
printSelf()
}
counter.increment(by: 2)
アンダースコア「_」を使用して外部パラメーター名を置き換えることもできるため、メソッドを呼び出すときに外部パラメーター名(パラメーターラベル)はありません。
func increment(_ count: Int) {
self.count += count
printSelf()
}
counter.increment(2)
インスタンスメソッドの値型を変更します
Swift言語の構造と列挙は値型です。通常の状況では、値型の属性をインスタンスメソッドで変更することはできません。
例えば:
struct Size {
var width = 10
var height = 20
// 以下方法报错
func increment(by amount: Int) {
width += amount;
height += amount;
}
}
ただし、特定のメソッドの構造または列挙のプロパティを本当に変更する必要がある場合は、このメソッドを変更することを選択できます。その後、メソッドはメソッド内からプロパティを変更できます。メソッドは、非表示にすることもできます。 self属性は、メソッドの最後にある既存のインスタンスを置き換える新しいインスタンスを提供します。
例えば:
struct Size {
var width = 10
var height = 20
mutating func increment(by amount: Int) {
width += amount;
height += amount;
}
}
var size = Size()
print("\(size)")
// Size(width: 10, height: 20)
size.increment(by: 5)
print("\(size)")
// Size(width: 15, height: 25)
可変メソッドで自分自身に値を割り当てる
上記の例では、次のように書き直すことができ、結果は同じです。
struct Size {
var width = 10
var height = 20
mutating func increment(by amount: Int) {
// width += amount;
// height += amount;
self = Size(width: width+amount, height: height+amount)
}
}
列挙の可変メソッドは、同じ列挙タイプの異なるメンバーに自分自身を設定できます。
enum TriStateSwitch {
case off, low, high
mutating func next() {
switch self {
case .off:
self = .low
case .low:
self = .high
case .high:
self = .off
}
}
}
var ovenLight = TriStateSwitch.low
ovenLight.next()
// ovenLight 现在等于 .high
ovenLight.next()
// ovenLight 现在等于 .off
タイプメソッド
インスタンスメソッドは、特定のタイプのインスタンスによって呼び出されます。
型メソッドは、型自体によって呼び出されます。
構造体と列挙型のtypeメソッドを宣言するには、メソッドのfuncキーワードの前にキーワードstaticを追加します。
クラスはキーワードclassを使用して、サブクラスが親クラスの実装メソッドをオーバーライドできるようにすることができます。
class Math {
class func abs(number: Int) -> Int {
if number < 0 {
return (-number)
}else {
return number
}
}
}
struct Sample {
static func abs(number: Int) -> Int {
if number < 0 {
return (-number)
}else {
return number
}
}
}
let number1 = Math.abs(number: -5)
let number2 = Sample.abs(number: -10)
print(number1)
print(number2)
/**
5
10
*/