Statische vs Klassenfunktionen / Variablen in Swift-Klassen?


416

Der folgende Code wird in Swift 1.2 kompiliert:

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

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

Was ist der Unterschied zwischen einer statischen Funktion und einer Klassenfunktion ? Welches soll ich wann verwenden?

Wenn ich versuche, eine andere Variable zu definieren class var myVar2 = "", heißt es:

In Klassen gespeicherte Eigenschaften von Klassen werden in Klassen noch nicht unterstützt. Meinten Sie "statisch"?

Wenn diese Funktion unterstützt wird, was ist der Unterschied zwischen einer statischen Variablen und einer Klassenvariablen (dh wenn beide in einer Klasse definiert sind)? Welches soll ich wann verwenden?

(Xcode 6.3)


Antworten:


689

staticund classbeide ordnen eine Methode einer Klasse zu und nicht einer Instanz einer Klasse. Der Unterschied besteht darin, dass Unterklassen classMethoden überschreiben können. Sie können staticMethoden nicht überschreiben .

class Eigenschaften funktionieren theoretisch auf die gleiche Weise (Unterklassen können sie überschreiben), sind jedoch in Swift noch nicht möglich.


89
Was ist also der Unterschied zwischen final classFunktion und 'statischer' Funktion innerhalb einer Klasse?
Hippo_san

57
@hippo_san, in einer Basisklasse sind die beiden funktional gleich. Jedoch finalkann verwendet werden , um weitere Überschreibungen abzuschneiden , wenn sie in einer Unterklasse verwendet. Die beiden haben ihren Platz, ich würde sagen, die Verwendung staticoder finalVerwendung einer Klassenfunktion ist trivial und hängt von Ihrer Stilwahl ab.
Andrew Robinson

8
ah, also static func foo(){}in Swift ist wie public static final foo(){}in Java?
Supuhstar

3
@Supuhstar: Grundsätzlich ja.
Mipadi

2
@ipadi Ich verstehe jetzt. Für Klassenfunktionen können wir "static" durch "final class" ersetzen, für Eigenschaften in einer Klasse können wir jedoch nur statische Eigenschaften anstelle von Klasseneigenschaften haben. Das Schlüsselwort "static" hat also immer noch seinen Platz.
Allenlinli

72

Ich versuchte es mit Mipadis Antwort und Kommentaren auf dem Spielplatz. Und dachte daran, es zu teilen. Bitte schön. Ich denke, Mipadis Antwort sollte als akzeptiert markiert werden.

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

In Bezug auf OOP ist die Antwort zu einfach:

Die Unterklassen können Klassenmethoden überschreiben, statische Methoden jedoch nicht .

Wenn Sie zusätzlich zu Ihrem Beitrag eine Klassenvariable deklarieren möchten (wie Sie es getan haben class var myVar2 = ""), sollten Sie dies wie folgt tun:

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

23

Ich habe diese Verwirrung auch in einem meiner Projekte bekommen und fand diesen Beitrag sehr hilfreich. Versuchte das gleiche auf meinem Spielplatz und hier ist die Zusammenfassung. Hoffe , dass dies jemand mit gespeicherten Eigenschaften und Funktionen des Typs hilft static, final, class, übergeordnete Klasse Vars usw.

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"
    }
}

Und hier sind die Testbeispiele:

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

Das Testen in Swift 4 zeigt Leistungsunterschiede im Simulator. Ich habe eine Klasse mit "class func" und eine Struktur mit "static func" erstellt und sie im Test ausgeführt.

statische Funktion ist:

  • 20% schneller ohne Compileroptimierung
  • 38% schneller, wenn die Optimierung der Gesamtmoduloptimierung aktiviert ist.

Das Ausführen des gleichen Codes auf dem iPhone 7 unter iOS 10.3 zeigt jedoch genau die gleiche Leistung.

Hier ist ein Beispielprojekt in Swift 4 für Xcode 9, wenn Sie sich selbst testen möchten: https://github.com/protyagov/StructVsClassPerformance


War dies auf dem Simulator oder dem physischen Gerät?
mmr118

7

Es gibt noch einen Unterschied. classkann verwendet werden, um nur Typeneigenschaften des berechneten Typs zu definieren . Wenn Sie eine gespeicherte Typeigenschaft benötigen, verwenden Sie staticstattdessen.

"Sie definieren Typeneigenschaften mit dem statischen Schlüsselwort. Für berechnete Typeneigenschaften für Klassentypen können Sie stattdessen das Klassenschlüsselwort verwenden, damit Unterklassen die Implementierung der Oberklasse überschreiben können."


7

Wenn statische Methoden zu den obigen Antworten hinzugefügt werden, bedeutet dies, dass der Compiler weiß, welche Methode zur Laufzeit ausgeführt wird, da die statische Methode nicht überschrieben werden kann, während die Klassenmethode ein dynamischer Versand sein kann, da die Unterklasse diese überschreiben kann.


0

Es gibt noch einen Unterschied. Klasse kann verwendet werden, um nur Typeneigenschaften des berechneten Typs zu definieren. Wenn Sie eine gespeicherte Typeigenschaft benötigen, verwenden Sie stattdessen static.

Klasse: - Referenztyp

struct: - Werttyp


0

classwird in Reference Type(Klasse) verwendet:

  • berechnete Eigenschaft
  • Methode
  • kann von der Unterklasse überschrieben werden

staticwird in Reference Typeund Value Type(Klasse, Aufzählung) verwendet:

  • berechnete Eigenschaft und gespeicherte Eigenschaft
  • Methode
  • kann nicht durch Unterklasse geändert werden
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

[Referenz vs Werttyp]

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.