C系言語(Objective-Cを含む)では、常に「クラスメソッド」(class methods)が存在していました。Swiftでは、そのようなメソッドがタイプに対して二つのタイプ、staticとclassで登場しました。これにより、インスタンスではなく、タイプ自体に対してメソッドを呼び出すことができます。staticは構造体や列挙体、継承できないクラスに対して使用され、一方、classは継承先でのオーバーライドが可能なクラスに使用されます。
問題: staticとclassの混乱は、継承が可能なクラス階層において、メソッドやプロパティのオーバーライドを子クラスに許可または拒否したい場合に生じます。
解決策:
コードの例:
class Animal { class func makeSound() { print("Some generic animal sound") } static func kingdom() -> String { "Animalia" } } class Dog: Animal { override class func makeSound() { print("Woof!") } // override static func kingdom() — エラー:staticはオーバーライドできません! } Animal.makeSound() // Some generic animal sound Dog.makeSound() // Woof! print(Animal.kingdom()) // Animalia
主な特徴:
structやenumでclass funcを使用できますか?
いいえ、class funcはクラスにのみ許可されています。Structやenumはstaticメソッドとプロパティのみをサポートします。
staticプロパティは計算可能であったり、変数(var)にすることができますか?
はい、staticプロパティは計算型(computed)または保存型(stored)で、static varを介して定義できます。Structとenumの場合、これが唯一の方法であり、インスタンスではなくタイプを介してプロパティを利用可能にします。
コードの例:
struct Counter { static var totalCount = 0 static var nextId: Int { totalCount += 1 return totalCount } }
クラスのインスタンスを通してclassメソッドを呼び出せますか?
はい、可能ですが推奨されません:classメソッドは常にタイプに関係し、特定のオブジェクトには関係しませんので、元のタイプまたはオーバーライドの挙動が呼び出されます。
オーバーライドが想定されていないのに、クラスの静的ユーティリティにclass funcを使用すること。
利点:
欠点:
定数とユーティリティにはstaticを使用し、実際にサブクラスで変更可能なファクトリメソッドにはclassを使用します。
利点:
欠点: