Swiftクラスの静的関数とクラス関数/変数?


416

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

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

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

静的関数とクラス関数の違いは何ですか?どれをいつ使用すればよいですか?

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

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

この機能がサポートされている場合、静的変数とクラス変数の違いは何ですか(つまり、両方がクラスで定義されている場合)?どれをいつ使用すればよいですか?

(Xcode 6.3)


回答:


690

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

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


89
ではfinal class、クラス内の関数と「静的」関数の違いは何ですか?
hippo_san 2015

57
@hippo_san、基本クラスでは、2つは機能的に同じです。ただし、finalサブクラスで使用する場合は、さらにオーバーライドを遮断するために使用できます。2つはどちらにも場所があります。クラス関数で使用する場合、staticまたはfinalクラス関数で使用する場合は、簡単で、スタイルの選択次第です。
Andrew Robinson

8
ああ、だからstatic func foo(){}Swiftのはpublic static final foo(){}Javaのようですか?
Supuhstar、2015

3
@Supuhstar:基本的にはい。
mipadi

2
@mipadiわかりました。クラス関数の場合、「静的」を「最終クラス」に置き換えることができますが、クラスのプロパティの場合は、クラスプロパティの代わりに静的プロパティのみを使用できます。したがって、「静的」キーワードはまだその場所を持っています。
アレンリンリ

72

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

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(){

    }
}

27

OOPについては、答えは単純すぎます。

サブクラスはクラスメソッドをオーバーライドできますが、静的メソッドをオーバーライドできません。

投稿に加えて、クラス変数を宣言したい場合は(そうしたようにclass var myVar2 = "")、次のように行う必要があります。

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

23

私のプロジェクトの1つでもこの混乱があり、この投稿はとても役に立ちました。私の遊び場で同じことを試しました、そしてここに要約があります。このタイプの保存特性および機能を持つ人役に立てば幸いstaticfinalclass、クラスをオーバーライドすることなどをvarsの

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

23

Swift 4でのテストは、シミュレーターでのパフォーマンスの違いを示しています。「クラス関数」でクラスを作成し、「静的関数」で構造体を作成して、テストで実行しました。

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

  • 20%コンパイラの最適化なしで高速
  • 最適化-whole-module-optimizationを有効にすると、38%高速化されます。

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

自分でテストしたい場合は、Xcode 9用のSwift 4のサンプルプロジェクトを次に示します 。https://github.com/protyagov/StructVsClassPerformance


これはシミュレータまたは物理デバイスのどちらでしたか?
mmr118 2018年

7

7

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


0

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

クラス:-参照型

構造体:-値のタイプ


0

class内部で使用されますReference Type(クラス):

  • 計算されたプロパティ
  • 方法
  • サブクラスによってオーバーライドできます

static内部で使用されReference TypeValue Type(クラス、列挙型):

  • 計算されたプロパティと保存されたプロパティ
  • 方法
  • サブクラスでは変更できません
protocol MyProtocol {
//    class var protocolClassVariable : Int { get }//ERROR: Class properties are only allowed within classes
    static var protocolStaticVariable : Int { get }

//    class func protocolClassFunc()//ERROR: Class methods are only allowed within classes
    static func protocolStaticFunc()
}

struct ValueTypeStruct: MyProtocol {
    //MyProtocol implementation begin
    static var protocolStaticVariable: Int = 1

    static func protocolStaticFunc() {

    }
    //MyProtocol implementation end

//    class var classVariable = "classVariable"//ERROR: Class properties are only allowed within classes
    static var staticVariable = "staticVariable"

//    class func classFunc() {} //ERROR: Class methods are only allowed within classes
    static func staticFunc() {}
}

class ReferenceTypeClass: MyProtocol {
    //MyProtocol implementation begin
    static var protocolStaticVariable: Int = 2

    static func protocolStaticFunc() {

    }
    //MyProtocol implementation end

    var variable = "variable"

//    class var classStoredPropertyVariable = "classVariable"//ERROR: Class stored properties not supported in classes

    class var classComputedPropertyVariable: Int {
        get {
            return 1
        }
    }

    static var staticStoredPropertyVariable = "staticVariable"

    static var staticComputedPropertyVariable: Int {
        get {
            return 1
        }
    }

    class func classFunc() {}
    static func staticFunc() {}
}

final class FinalSubReferenceTypeClass: ReferenceTypeClass {
    override class var classComputedPropertyVariable: Int {
        get {
            return 2
        }
    }
    override class func classFunc() {}
}

//class SubFinalSubReferenceTypeClass: FinalSubReferenceTypeClass {}// ERROR: Inheritance from a final class

[参照と値のタイプ]

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.