Fonctions / variables statiques vs classe dans les classes Swift?


416

Le code suivant se compile 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 de classe ? Laquelle dois-je utiliser et quand?

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

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

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

(Xcode 6.3)


Réponses:


690

staticet les classdeux associent une méthode à une classe, plutôt qu'une instance d'une classe. La différence est que les sous-classes peuvent remplacer les classméthodes; ils ne peuvent pas remplacer les staticméthodes.

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


89
Quelle est donc la différence entre la final classfonction et la fonction «statique» au sein d'une classe?
hippo_san

57
@hippo_san, dans une classe de base, les deux sont fonctionnellement les mêmes. Cependant, finalpeut être utilisé pour supprimer d'autres remplacements lorsqu'il est utilisé dans une sous-classe. Les deux ont leur place, je dirais que l'utilisation staticou finallorsqu'elle est utilisée sur une fonction de classe est triviale et dépend de votre choix de style.
Andrew Robinson

8
ah, donc static func foo(){}dans Swift, c'est comme public static final foo(){}dans Java?
Supuhstar

3
@Supuhstar: Fondamentalement, oui.
mipadi

2
@mipadi je comprends maintenant. Pour les fonctions de classe, nous pouvons remplacer "statique" par "classe finale", mais pour les propriétés d'une classe, nous ne pouvons avoir que des propriétés statiques au lieu des propriétés de classe. Le mot-clé "statique" a donc toujours sa place.
allenlinli

72

J'ai essayé la réponse et les commentaires de mipadi sur le terrain de jeu. Et j'ai pensé à le partager. Voici. Je pense que la réponse de mipadi devrait être considéré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(){

    }
}

27

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

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

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

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

23

J'ai également eu cette confusion dans l'un de mes projets et j'ai trouvé ce message très utile. J'ai essayé la même chose dans ma cour de récréation et voici le résumé. Espérons que cela aide quelqu'un avec des propriétés stockées et fonctions de type static, final, class, classe remplaçant vars 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

23

Les tests dans Swift 4 montrent la différence de performances dans le simulateur. J'ai fait une classe avec "class func" et struct avec "static func" et les ai exécutés en test.

la fonction statique est:

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

Cependant, l'exécution du même code sur iPhone 7 sous iOS 10.3 affiche exactement les mêmes performances.

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


était-ce sur le simulateur ou le périphérique physique?
mmr118

7

Il y a encore une différence. classpeut être utilisé pour définir des propriétés de type de type calculé uniquement . Si vous avez besoin d'une propriété de type stockée, utilisez staticplutôt.

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


7

Ajouter aux réponses ci-dessus les méthodes statiques sont une répartition statique signifie que le compilateur sait quelle méthode sera exécutée au moment de l'exécution car la méthode statique ne peut pas être remplacée tandis que la méthode de classe peut être une répartition dynamique car la sous-classe peut les remplacer.


0

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

Classe: - type de référence

struct: - type de valeur


0

classest utilisé à l'intérieur Reference Type(classe):

  • propriété calculée
  • méthode
  • peut être remplacé par une sous-classe

staticest utilisé à l'intérieur Reference Typeet Value Type(classe, énum):

  • propriété calculée et propriété stockée
  • méthode
  • ne peut pas être modifié par sous-classe
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

[Référence vs type de valeur]

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.