简体   繁体   English

Swift 类中的静态与类函数/变量?

[英]Static vs class functions/variables in Swift classes?

The following code compiles in Swift 1.2:以下代码在 Swift 1.2 中编译:

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

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

What is the difference between a static function and a class function?静态函数和函数有什么区别? Which one should I use, and when?我应该使用哪一种,什么时候使用?

If I try to define another variable class var myVar2 = "" , it says:如果我尝试定义另一个变量class var myVar2 = "" ,它会说:

Class stored properties not yet supported in classes;类中尚不支持类存储属性; did you mean 'static'?您指的是 'static' 吗?

When this feature is supported, what will the difference be between a static variable and a class variable (ie when both are defined in a class)?当这个特性被支持时,静态变量和变量之间有什么区别(即当两者都定义在一个类中时)? Which one should I use, and when?我应该使用哪一种,什么时候使用?

(Xcode 6.3) (Xcode 6.3)

static and class both associate a method with a class, rather than an instance of a class. staticclass都将方法与class相关联,而不是类的实例。 The difference is that subclasses can override class methods;不同之处在于子类可以覆盖class方法; they cannot override static methods.它们不能覆盖static方法。

class properties will theoretically function in the same way (subclasses can override them), but they're not possible in Swift yet. class属性理论上将以相同的方式运行(子类可以覆盖它们),但它们在 Swift 中尚不可用。

I tried mipadi's answer and comments on playground.我在操场上尝试了 mipadi 的回答和评论。 And thought of sharing it.并想到了分享。 Here you go.干得好。 I think mipadi's answer should be mark as accepted.我认为 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(){
        
    }
}

Regarding to OOP , the answer is too simple:关于OOP ,答案太简单了:

The subclasses can override class methods, but cannot override static methods.子类可以覆盖方法,但不能覆盖静态方法。

In addition to your post, if you want to declare a class variable (like you did class var myVar2 = "" ), you should do it as follow:除了你的帖子,如果你想声明一个变量(就像你所做的class var myVar2 = "" ),你应该这样做:

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

Testing in Swift 4 shows performance difference in simulator.在 Swift 4 中的测试显示了模拟器的性能差异。 I made a class with "class func" and struct with "static func" and ran them in test.我用“class func”创建了一个类,用“static func”创建了一个结构体,并在测试中运行它们。

static func is:静态函数是:

  • 20% faster without compiler optimization无需编译器优化,速度提高20%
  • 38% faster when optimization -whole-module-optimization is enabled.启用优化 -whole-module-optimization 时,速度提高38%

However, running the same code on iPhone 7 under iOS 10.3 shows exactly the same performance.但是,在 iOS 10.3 下的 iPhone 7 上运行相同的代码显示出完全相同的性能。

Here is sample project in Swift 4 for Xcode 9 if you like to test yourself https://github.com/protyagov/StructVsClassPerformance如果您想测试自己,这里是 Swift 4 for Xcode 9 中的示例项目https://github.com/protyagov/StructVsClassPerformance

I got this confusion in one of my project as well and found this post, very helpful.我在我的一个项目中也遇到了这种困惑,并发现这篇文章非常有帮助。 Tried the same in my playground and here is the summary.在我的操场上尝试过相同的方法,这是摘要。 Hope this helps someone with stored properties and functions of type static , final , class , overriding class vars etc.希望这可以帮助拥有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"
    }
}

And here is the testing samples:这是测试样本:

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

There's one more difference.还有一个区别。 class can be used to define type properties of computed type only . class只能用于定义计算类型的类型属性。 If you need a stored type property use static instead.如果您需要存储类型属性,请改用static

"You define type properties with the static keyword. For computed type properties for class types, you can use the class keyword instead to allow subclasses to override the superclass's implementation." “您使用 static 关键字定义类型属性。对于类类型的计算类型属性,您可以改用 class 关键字以允许子类覆盖超类的实现。”

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

class vs static类与静态

[Reference vs Value Type] [引用 vs 值类型]

class is used inside Reference Type (class, function): classReference Type (类,函数)中使用:

  • computed property计算属性
  • method方法
  • can be overridden by subclass可以被子类覆盖

static is used inside Reference Type (class, function) and Value Type (struct, enum, tuple): static用于Reference Type (类、函数)和Value Type (结构、枚举、元组):

  • computed property and stored property计算属性和存储属性
  • method方法
  • cannot be changed by subclass子类不能改变
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

There's one more difference.还有一个区别。 class can be used to define type properties of computed type only. class 只能用于定义计算类型的类型属性。 If you need a stored type property use static instead.如果您需要存储类型属性,请改用静态。

Class :- reference type类:- 引用类型

struct :- value type struct :- 值类型

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM