web-dev-qa-db-ja.com

Swiftクラスにおける静的vsクラス関数/変数

次のコードはSwift 1.2でコンパイルされています。

class myClass {
    static func myMethod1() {
    }
    class func myMethod2() {
    }
    static var myVar1 = ""
}

func doSomething() {
    myClass.myMethod1()
    myClass.myMethod2()
    myClass.myVar1 = "abc"
}

static functionと class functionの違いは何ですか?どれをいつ使うべきですか?

別の変数class var myVar2 = ""を定義しようとすると、次のようになります。

クラスに格納されたプロパティはまだクラスではサポートされていません。 「静的」という意味ですか?

この機能がサポートされている場合、 static 変数と class 変数の違いは何になりますか(つまり、両方がクラスで定義されている場合)どれをいつ使うべきですか?

(Xcode 6.3)

377
Senseful

staticclassはどちらもメソッドをクラスのインスタンスではなくクラスに関連付けます。違いは、サブクラスがclassメソッドをオーバーライドできることです。 staticメソッドをオーバーライドすることはできません。

classプロパティは理論的には同じように機能します(サブクラスはそれらをオーバーライドできます)が、Swiftではまだ不可能です。

610
mipadi

私は遊び場でミパディの答えとコメントを試してみました。そしてそれを共有することを考えました。どうぞ。私はミパディの答えは受け入れられたものとしてマークすべきだと思います。

class A{
    class func classFunction(){
    }
    static func staticFunction(){
    }
    class func classFunctionToBeMakeFinalInImmediateSubclass(){
    }
}

class B: A {
    override class func classFunction(){

    }

    //Compile Error. Class method overrides a 'final' class method
    override static func staticFunction(){

    }

    //Lets avoid the function called 'classFunctionToBeMakeFinalInImmediateSubclass' being overriden by subclasses

    /* First way of doing it
    override static func classFunctionToBeMakeFinalInImmediateSubclass(){
    }
    */

    // Second way of doing the same
    override final class func classFunctionToBeMakeFinalInImmediateSubclass(){
    }

    //To use static or final class is choice of style.
    //As mipadi suggests I would use. static at super class. and final class to cut off further overrides by a subclass
}

class C: B{
    //Compile Error. Class method overrides a 'final' class method
    override static func classFunctionToBeMakeFinalInImmediateSubclass(){

    }
}
61
MadNik

私は自分のプロジェクトの1つでもこの混乱を招き、この記事がとても役に立ちました。私の遊び場でも同じことを試みましたが、ここに要約があります。これがstatic型、final型、class型の上書きされたクラスvarなどのプロパティと関数を格納している人に役立つことを願います。

class Simple {

    init() {print("init method called in base")}

    class func one() {print("class - one()")}

    class func two() {print("class - two()")}

    static func staticOne() {print("staticOne()")}

    static func staticTwo() {print("staticTwo()")}

    final func yesFinal() {print("yesFinal()")}

    static var myStaticVar = "static var in base"

    //Class stored properties not yet supported in classes; did you mean 'static'?
    class var myClassVar1 = "class var1"

    //This works fine
    class var myClassVar: String {
       return "class var in base"
    }
}

class SubSimple: Simple {
    //Successful override
    override class func one() {
        print("subClass - one()")
    }
    //Successful override
    override class func two () {
        print("subClass - two()")
    }

    //Error: Class method overrides a 'final' class method
    override static func staticOne() {

    }

    //error: Instance method overrides a 'final' instance method
    override final func yesFinal() {

    }

    //Works fine
    override class var myClassVar: String {
        return "class var in subclass"
    }
}

これがテストサンプルです。

print(Simple.one())
print(Simple.two())
print(Simple.staticOne())
print(Simple.staticTwo())
print(Simple.yesFinal(Simple()))
print(SubSimple.one())
print(Simple.myStaticVar)
print(Simple.myClassVar)
print(SubSimple.myClassVar)

//Output
class - one()
class - two()
staticOne()
staticTwo()
init method called in base
(Function)
subClass - one()
static var in base
class var in base
class var in subclass
21
Santosh

_ oop _ に関しては、答えは単純すぎます。

サブクラスは class methodsをオーバーライドできますが、 static methodsをオーバーライドすることはできません。

あなたの投稿に加えて、 class 変数を宣言したいのなら(class var myVar2 = ""のように)、次のようにするべきです:

class var myVar2: String {
    return "whatever you want"
}
21
eMdOS

Swift 4でのテストは、シミュレータでのパフォーマンスの違いを示しています。私は "class func"を使ってクラスを作り、 "static func"を使って構造化し、それらをテストで実行しました。

静的関数は次のとおりです。

  • 20% コンパイラの最適化なしで高速
  • 38% 最適化-whole-module-最適化が有効になっていると速くなります。

ただし、iOS 10.3のiPhone 7で同じコードを実行してもまったく同じパフォーマンスが得られます。

Swift 4のXcode 9用のサンプルプロジェクトです。 https://github.com/protyagov/StructVsClassPerformance

18
Alex Protyagov

もう1つ違いがあります。 classは、 計算型のみ の型プロパティを定義するために使用できます。 ストアドタイププロパティが必要な場合は 代わりにstaticを使用してください。

" " staticキーワードを使用して型プロパティを定義します。クラス型の計算型プロパティの場合は、代わりにclassキーワードを使用して、サブクラスがスーパークラスの実装をオーバーライドできるようにします。 "

6
Maciek Czarnik

上記の答えに加えて、静的メソッドは静的ディスパッチであり、静的メソッドはオーバーライドできないため、実行時にどのメソッドが実行されるかをコンパイラが認識します。

3
Ankit garg