【问题标题】:Static vs class functions/variables in Swift classes?Swift 类中的静态与类函数/变量?
【发布时间】:2015-06-20 14:40:36
【问题描述】:

以下代码在 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 = "",它会说:

类中尚不支持类存储的属性;您的意思是“静态”吗?

如果支持此功能,static 变量和 class 变量之间有什么区别(即两者都定义在一个类中时)?我应该使用哪一个,何时使用?

(Xcode 6.3)

【问题讨论】:

标签: function class swift variables static


【解决方案1】:

staticclass 都将方法与类相关联,而不是与类的实例相关联。不同的是子类可以覆盖class方法;他们不能覆盖static 方法。

class 属性理论上会以相同的方式发挥作用(子类可以覆盖它们),但它们在 Swift 中尚不可行。

【讨论】:

  • 那么final class函数和类中的“静态”函数有什么区别?
  • @hippo_san,在一个基类中,两者在功能上是相同的。但是,final 在子类中使用时可用于切断进一步的覆盖。两者都有自己的位置,我想说在类函数上使用 staticfinal 是微不足道的,取决于您的风格选择。
  • 啊,所以 Swift 中的 static func foo(){} 就像 Java 中的 public static final foo(){}
  • @Supuhstar:基本上,是的。
  • @mipadi 我现在明白了。对于类函数,我们可以将“static”替换为“final class”,但是对于类中的属性,我们可以只有静态属性而不是类属性。所以“静态”关键字仍然占有一席之地。
【解决方案2】:

我在操场上尝试了 mipadi 的答案和 cmets。并想到分享它。干得好。我认为 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(){
        
    }
    
    //Let's 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(){
        
    }
}

【讨论】:

    【解决方案3】:

    关于OOP,答案太简单了:

    子类可以覆盖方法,但不能覆盖静态方法。

    除了你的帖子,如果你想声明一个 class 变量(就像你做的class var myVar2 = ""),你应该这样做:

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

    【讨论】:

      【解决方案4】:

      在 Swift 4 中的测试显示了模拟器中的性能差异。我用“class func”创建了一个类,用“static func”创建了一个结构,并在测试中运行它们。

      静态函数是:

      • 20% 速度更快,无需编译器优化
      • 38% 启用优化 -whole-module-optimization 后速度加快。

      但是,在 iOS 10.3 下的 iPhone 7 上运行相同的代码显示出完全相同的性能。

      如果您想测试自己,这里是 Xcode 9 的 Swift 4 示例项目 https://github.com/protyagov/StructVsClassPerformance

      【讨论】:

      • 这是在模拟器还是物理设备上?
      【解决方案5】:

      我在我的一个项目中也遇到了这种困惑,发现这篇文章非常有帮助。在我的操场上尝试过同样的方法,这里是总结。希望这可以帮助具有staticfinalclass、覆盖类变量等类型的存储属性和函数的人。

      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
      

      【讨论】:

        【解决方案6】:

        Swift 类 vs 静态

        [Reference vs Value Type]

        classReference Type(类,函数)中使用:

        • 计算属性
        • 方法
        • 可以被子类覆盖

        static 用于Reference Type(class, function) 和Value Type(struct, enum, tuple):

        • 计算属性和存储属性
        • 方法
        • 不能由子类更改
        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
        
        

        【讨论】:

          【解决方案7】:

          添加到上面的答案静态方法是静态调度意味着编译器知道哪个方法将在运行时执行,因为静态方法不能被覆盖,而类方法可以是动态调度,因为子类可以覆盖这些。

          【讨论】:

            【解决方案8】:

            还有一个区别:class 可用于定义仅限计算类型的类型属性。如果您需要存储类型属性,请改用static

            您使用 static 关键字定义类型属性。对于类类型的计算类型属性,您可以使用 class 关键字来允许子类覆盖超类的实现。

            https://docs.swift.org/swift-book/LanguageGuide/Properties.html

            【讨论】:

            • 男士仔细阅读那篇文章并与您的“答案”进行比较。您可以将static 用于计算属性和存储属性。区别是use the class keyword instead to allow subclasses to override the superclass’s implementation
            猜你喜欢
            • 2016-08-30
            • 2015-05-26
            • 1970-01-01
            • 2014-10-10
            • 2017-08-25
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多