web-dev-qa-db-fra.com

Fonctions / variables statiques vs classes dans Swift classes?

Le code suivant est compilé dans Swift 1.2:

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

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

Quelle est la différence entre une fonction statique et une fonction classe? Lequel devrais-je utiliser et quand?

Si j'essaie de définir une autre variable class var myVar2 = "", elle indique:

Propriétés de classe stockées non encore prises en charge dans les classes; Voulez-vous dire "statique"?

Lorsque cette fonctionnalité est prise en charge, quelle sera la différence entre une variable statique et une variable classe (c'est-à-dire lorsque les deux sont définis dans une classe)? Lequel devrais-je utiliser et quand?

(Xcode 6.3)

392
Senseful

static et class associent tous deux une méthode à une classe plutôt qu'à une instance de classe. La différence est que les sous-classes peuvent remplacer les méthodes class; ils ne peuvent pas écraser les méthodes static.

Les propriétés class fonctionnent théoriquement de la même manière (les sous-classes peuvent les remplacer), mais elles ne sont pas encore possibles dans Swift.

638
mipadi

J'ai essayé la réponse et les commentaires de Mipadi sur le terrain de jeu. Et pensé à le partager. Voici. Je pense que la réponse de Mipadi devrait être marquée comme acceptée.

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

    }
}
64
MadNik

En ce qui concerne OOP, la réponse est trop simple:

Les sous-classes peuvent remplacer les méthodes classe, mais ne peuvent pas remplacer les méthodes statique.

En plus de votre message, si vous souhaitez déclarer une variable class (comme vous l'avez fait class var myVar2 = ""), procédez comme suit:

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

J'ai également eu cette confusion dans l'un de mes projets et j'ai trouvé ce post très utile. Essayé la même chose dans mon terrain de jeu et voici le résumé. J'espère que cela aidera quelqu'un avec des propriétés et des fonctions stockées de type static, final, class, écrasant les variables de classe, etc.

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

Et voici les échantillons de test:

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

Le test dans Swift 4 montre une différence de performance dans le simulateur. J'ai fait une classe avec "class func" et une structure avec "static func" et les ai exécutées dans le test.

statique func est:

  • 20% plus rapide sans optimisation du compilateur
  • 38% plus rapidement lorsque l'optimisation -whole-module-optimisation est activée.

Cependant, exécuter le même code sur l'iPhone 7 sous iOS 10.3 montre exactement les mêmes performances.

Voici un exemple de projet dans Swift 4 pour Xcode 9 si vous souhaitez vous tester https://github.com/protyagov/StructVsClassPerformance

18
Alex Protyagov

Il y a une autre différence. class peut être utilisé pour définir les propriétés de type de type calculé uniquement . Si vous avez besoin d'une propriété de type stocké , utilisez plutôt static.

"Vous définissez les propriétés de type avec le mot clé static. Pour les propriétés de type calculées pour les types de classe, vous pouvez utiliser le mot clé class afin de permettre aux sous-classes de remplacer l'implémentation de la superclasse."

7
Maciek Czarnik

L'ajout aux réponses ci-dessus est une méthode de répartition statique qui signifie que le compilateur sait quelle méthode sera exécutée à l'exécution, car la méthode statique ne peut pas être remplacée, alors que la méthode class peut être une répartition dynamique, car la sous-classe peut les remplacer.

4
Ankit garg