我可以在Swift库中看到这些定义:

extension Bool : BooleanLiteralConvertible {
    static func convertFromBooleanLiteral(value: Bool) -> Bool
}

protocol BooleanLiteralConvertible {
    typealias BooleanLiteralType
    class func convertFromBooleanLiteral(value: BooleanLiteralType) -> Self
}

定义为静态func的成员函数和定义为类func的成员函数之间有什么区别?是不是简单地说,static是用于结构体和枚举的静态函数,class是用于类和协议?还有其他不同之处吗?在语法本身中有这种区别的基本原理是什么?


当前回答

根据苹果公司发布的Swift 2.2 Book:

通过在方法的func关键字之前写入static关键字来指示类型方法。类也可以使用class关键字来允许子类重写父类对该方法的实现。”

其他回答

static和class关键字都允许我们将方法附加到类而不是类的实例。例如,您可以创建一个具有名称和年龄等属性的Student类,然后创建一个静态方法numberOfStudents,该方法由Student类本身而不是单个实例拥有。

静态和类的不同之处在于它们支持继承的方式。当你创建一个静态方法时,它被类拥有,不能被子类改变,而当你使用类时,它可能会在需要时被覆盖。

下面是一个示例代码:

class Vehicle {
    static func getCurrentSpeed() -> Int {
        return 0
    }
    
    class func getCurrentNumberOfPassengers() -> Int {
        return 0
    } 
}

class Bicycle: Vehicle {
    //This is not allowed
    //Compiler error: "Cannot override static method"
    //static override func getCurrentSpeed() -> Int {
        //return 15
    //}
    
    class override func getCurrentNumberOfPassengers() -> Int {
        return 1
    }
}

这个例子将清楚每一个方面!

import UIKit

class Parent {
    final func finalFunc() -> String { // Final Function, cannot be redeclared.
        return "Parent Final Function."
    }

    static func staticFunc() -> String { // Static Function, can be redeclared.
        return "Parent Static Function."
    }

    func staticFunc() -> String { // Above function redeclared as Normal function.
        return "Parent Static Function, redeclared with same name but as non-static(normal) function."
    }

    class func classFunc() -> String { // Class Function, can be redeclared.
        return "Parent Class Function."
    }

    func classFunc() -> String { // Above function redeclared as Normal function.
        return "Parent Class Function, redeclared with same name but as non-class(normal) function."
    }

    func normalFunc() -> String { // Normal function, obviously cannot be redeclared.
        return "Parent Normal Function."
    }
}

class Child:Parent {

    // Final functions cannot be overridden.

    override func staticFunc() -> String { // This override form is of the redeclared version i.e: "func staticFunc()" so just like any other function of normal type, it can be overridden.
        return "Child Static Function redeclared and overridden, can simply be called Child Normal Function."
    }

    override class func classFunc() -> String { // Class function, can be overidden.
        return "Child Class Function."
    }

    override func classFunc() -> String { // This override form is of the redeclared version i.e: "func classFunc()" so just like any other function of normal type, it can be overridden.
        return "Child Class Function, redeclared and overridden, can simply be called Child Normal Function."
    }

    override func normalFunc() -> String { // Normal function, can be overridden.
        return "Child Normal Function."
    }
}

let parent = Parent()
let child = Child()

// Final
print("1. " + parent.finalFunc())   // 1. Can be called by object.
print("2. " + child.finalFunc())    // 2. Can be called by object, parent(final) function will be called.
// Parent.finalFunc()               // Cannot be called by class name directly.
// Child.finalFunc()                // Cannot be called by class name directly.

// Static
print("3. " + parent.staticFunc())  // 3. Cannot be called by object, this is redeclared version (i.e: a normal function).
print("4. " + child.staticFunc())   // 4. Cannot be called by object, this is override form redeclared version (normal function).
print("5. " + Parent.staticFunc())  // 5. Can be called by class name directly.
print("6. " + Child.staticFunc())   // 6. Can be called by class name direcly, parent(static) function will be called.

// Class
print("7. " + parent.classFunc())   // 7. Cannot be called by object, this is redeclared version (i.e: a normal function).
print("8. " + child.classFunc())    // 8. Cannot be called by object, this is override form redeclared version (normal function).
print("9. " + Parent.classFunc())   // 9. Can be called by class name directly.
print("10. " + Child.classFunc())   // 10. Can be called by class name direcly, child(class) function will be called.

// Normal
print("11. " + parent.normalFunc())  // 11. Can be called by object.
print("12. " + child.normalFunc())   // 12. Can be called by object, child(normal) function will be called.
// Parent.normalFunc()               // Cannot be called by class name directly.
// Child.normalFunc()                // Cannot be called by class name directly.

/*
 Notes:
 ___________________________________________________________________________
 |Types------Redeclare------Override------Call by object------Call by Class|
 |Final----------0--------------0---------------1------------------0-------|
 |Static---------1--------------0---------------0------------------1-------|
 |Class----------1--------------1---------------0------------------1-------|
 |Normal---------0--------------1---------------1------------------0-------|
 ---------------------------------------------------------------------------

 Final vs Normal function: Both are same but normal methods can be overridden.
 Static vs Class function: Both are same but class methods can be overridden.
 */

输出:

为了更清楚,我举个例子,

class ClassA {
    class func func1() -> String {
        return "func1"
    }
    
    static func func2() -> String {
        return "func2"
    }
}

/* same as above
    final class func func2() -> String {
        return "func2"
    }
*/

静态func与最终类func相同

因为它是final的,所以我们不能在子类中重写它,如下所示:

class ClassB : ClassA {
    override class func func1() -> String {
        return "func1 in ClassB"
}
    
// ERROR: Class method overrides a 'final` class method
override static func func2() -> String {
        return "func2 in ClassB"
    }
}

来自Swift2.0,苹果表示:

“当你在协议中定义类型属性需求时,总是用static关键字作为前缀。当类实现时,即使类型属性要求可以用class或static关键字作为前缀,该规则也适用:"

若要声明类型变量属性,请使用静态声明修饰符标记声明。类可以用类声明修饰符标记类型计算属性,以允许子类重写超类的实现。类型属性在类型属性中讨论。 请注意 在类声明中,关键字static与同时使用类和final声明修饰符标记声明具有相同的效果。

来源:Swift编程语言-类型变量属性