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

Static vs class functions/variables in Swift classes?

以下代码在SWIFT 1.2中编译:

1
2
3
4
5
6
7
8
9
10
11
12
13
class myClass {
    static func myMethod1() {
    }
    class func myMethod2() {
    }
    static var myVar1 =""
}

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

静态函数和类函数有什么区别?我应该用哪一个,什么时候用?

如果我试图定义另一个变量class var myVar2 ="",它会说:

Class stored properties not yet supported in classes; did you mean 'static'?

当支持这个特性时,静态变量和类变量之间的区别是什么(即当两个变量都在一个类中定义时)?我应该用哪一个,什么时候用?

(XCODER 6.3)


staticclass都将方法与类关联,而不是类的实例。区别在于子类可以重写class方法;它们不能重写static方法。

理论上,class属性将以相同的方式工作(子类可以覆盖它们),但它们在swift中还不可能实现。


我在操场上试过米帕迪的回答和评论。想分享一下。干得好。我认为米帕迪的回答应该是"接受"。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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(){

    }
}


关于OOP,答案太简单了:

子类可以重写类方法,但不能重写静态方法。

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

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

我在我的一个项目中也遇到了这种困惑,我发现这篇文章非常有帮助。我在操场上也试过,下面是总结。希望这可以帮助用户使用static类型、final类型、class类型、重写类vars等存储属性和函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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"
    }
}

以下是测试样本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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

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

静态功能是:

  • 无需编译器优化,速度快20%
  • 当优化-启用整个模块优化时,速度加快38%。

然而,在iOS 10.3下的iPhone7上运行相同的代码显示出完全相同的性能。

这是Xcode9的swift 4示例项目,如果您想测试自己的话。https://github.com/protyagov/structvsclassperformance


还有一个区别。class只能用于定义计算类型的类型属性。如果需要存储类型属性,请使用static

"使用静态关键字定义类型属性。对于类类型的计算类型属性,可以使用class关键字来允许子类重写超类的实现。"


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