Swiftライブラリでこれらの定義を見ることができます。
extension Bool : BooleanLiteralConvertible {
static func convertFromBooleanLiteral(value: Bool) -> Bool
}
protocol BooleanLiteralConvertible {
typealias BooleanLiteralType
class func convertFromBooleanLiteral(value: BooleanLiteralType) -> Self
}
static func
として定義されているメンバ関数とclass func
として定義されている別のメンバ関数の違いは何ですか? static
が構造体と列挙型の静的関数用で、class
がクラスとプロトコル用であるということですか?他に知っておくべき違いはありますか?構文自体にこの区別がある理由は何ですか?
単にstaticが構造体と列挙型の静的関数のためのものであり、クラスとプロトコルのためのクラスのためだけのものですか?
それが主な違いです。その他の違いは、クラス関数は動的にディスパッチされ、サブクラスによってオーバーライドされる可能性があることです。
プロトコルはclassキーワードを使用しますが、プロトコルの実装から構造体を除外するのではなく、代わりにstaticを使用します。プロトコルにはクラスが選択されているので、静的またはクラスを表すための3番目のキーワードは必要ありません。
このトピックに関するChris Lattnerから:
構文を統一することを検討しました(たとえば、キーワードとして "type"を使用するなど)が、実際にはそれだけではありません。キーワード "class"と "static"は、慣れ親しんだものであり、(メソッドがどのように機能するかを理解したら)非常に説明的なものであり、クラスに本当に静的なメソッドを追加する可能性があります。このモデルの主な奇妙な点は、プロトコルがキーワードを選択しなければならないことです(そして「クラス」を選択しました)が、バランスの取れたところでそれは正しいトレードオフです。
そして、これがクラス関数のオーバーライド動作のいくつかを示すスニペットです。
class MyClass {
class func myFunc() {
println("myClass")
}
}
class MyOtherClass: MyClass {
override class func myFunc() {
println("myOtherClass")
}
}
var x: MyClass = MyOtherClass()
x.dynamicType.myFunc() //myOtherClass
x = MyClass()
x.dynamicType.myFunc() //myClass
より明確にするために、ここで例を挙げます。
class ClassA {
class func func1() -> String {
return "func1"
}
static func func2() -> String {
return "func2"
}
/* same as above
final class func func2() -> String {
return "func2"
}
*/
}
static func
はfinal class func
と同じです
これはfinal
なので、以下のようにサブクラスでオーバーライドすることはできません。
class ClassB : ClassA {
override class func func1() -> String {
return "func1 in ClassB"
}
// ERROR: Class method overrides a 'final` class method
override static func func2() -> String {
return "func2 in ClassB"
}
}
私は遊び場でいくつか実験をし、いくつかの結論を得ました。
ご覧のとおり、class
の場合、class func
またはstatic func
の使用は単なる習慣の問題です。
説明付きの遊び場の例:
class Dog {
final func identity() -> String {
return "Once a woofer, forever a woofer!"
}
class func talk() -> String {
return "Woof woof!"
}
static func eat() -> String {
return "Miam miam"
}
func sleep() -> String {
return "Zzz"
}
}
class Bulldog: Dog {
// Can not override a final function
// override final func identity() -> String {
// return "I'm once a dog but now I'm a cat"
// }
// Can not override a "class func", but redeclare is ok
func talk() -> String {
return "I'm a bulldog, and I don't woof."
}
// Same as "class func"
func eat() -> String {
return "I'm a bulldog, and I don't eat."
}
// Normal function can be overridden
override func sleep() -> String {
return "I'm a bulldog, and I don't sleep."
}
}
let dog = Dog()
let bullDog = Bulldog()
// FINAL FUNC
//print(Dog.identity()) // compile error
print(dog.identity()) // print "Once a woofer, forever a woofer!"
//print(Bulldog.identity()) // compile error
print(bullDog.identity()) // print "Once a woofer, forever a woofer!"
// => "final func" is just a "normal" one but prevented to be overridden nor redeclared by subclasses.
// CLASS FUNC
print(Dog.talk()) // print "Woof woof!", called directly from class
//print(dog.talk()) // compile error cause "class func" is meant to be called directly from class, not an instance.
print(Bulldog.talk()) // print "Woof woof!" cause it's called from Bulldog class, not bullDog instance.
print(bullDog.talk()) // print "I'm a bulldog, and I don't woof." cause talk() is redeclared and it's called from bullDig instance
// => "class func" is like a "static" one, must be called directly from class or subclassed, can be redeclared but NOT meant to be overridden.
// STATIC FUNC
print(Dog.eat()) // print "Miam miam"
//print(dog.eat()) // compile error cause "static func" is type method
print(Bulldog.eat()) // print "Miam miam"
print(bullDog.eat()) // print "I'm a bulldog, and I don't eat."
// NORMAL FUNC
//print(Dog.sleep()) // compile error
print(dog.sleep()) // print "Zzz"
//print(Bulldog.sleep()) // compile error
print(bullDog.sleep()) // print "I'm a bulldog, and I don't sleep."
型変数プロパティを宣言するには、宣言に
static
宣言修飾子を付けて宣言します。サブクラスがスーパークラスの実装をオーバーライドできるようにするために、クラスは代わりにclass
宣言修飾子で型計算されたプロパティをマークすることができます。型プロパティについては、型プロパティで説明しています。NOTE
クラス宣言において、キーワードstatic
は、class
およびfinal
宣言修飾子の両方で宣言をマークするのと同じ効果があります。
アップルが発行したSwift 2.2 Bookによると、
「メソッドのfuncキーワードの前にstatic
キーワードを書くことで型メソッドを指定します。また、クラスはclass
キーワードを使用して、サブクラスがそのメソッドのスーパークラスの実装をオーバーライドできるようにすることもできます。
Swift2.0以降、Appleは次のように述べています。
「プロトコルで定義するときは、常にtypeキーワードの要件にstaticキーワードを付ける