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

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

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

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


当前回答

是不是简单地说,static是用于结构体和枚举的静态函数,class是用于类和协议?

这是主要的区别。其他一些不同之处在于类函数是动态分派的,并且可以被子类覆盖。

协议使用class关键字,但它不排除实现协议的结构,而是使用static。Class是为协议选择的,这样就不需要第三个关键字来表示静态或类。

下面是克里斯·拉特纳对这个话题的看法:

我们考虑统一语法(例如使用“type”作为关键字),但这实际上并不能简化事情。关键字“类”和“静态”有助于熟悉并具有相当的描述性(一旦您理解了+方法的工作方式),并为潜在地向类添加真正的静态方法打开了大门。这个模型的主要奇怪之处在于协议必须选择一个关键字(我们选择了“类”),但总的来说,这是正确的权衡。

下面是一个片段,展示了类函数的一些重写行为:

class MyClass {
    class func myFunc() {
        println("myClass")
    }
}

class MyOtherClass: MyClass {
    override class func myFunc() {
        println("myOtherClass")
    }
}

var x: MyClass = MyOtherClass()
x.dynamicType.myFunc() //myOtherClass
x = MyClass()
x.dynamicType.myFunc() //myClass

其他回答

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

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"
    }
}

这被称为类型方法,并且像实例方法一样使用点语法调用。但是,在类型上调用类型方法,而不是在该类型的实例上调用类型方法。下面是如何在一个名为SomeClass的类上调用类型方法:

来自Swift2.0,苹果表示:

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

是不是简单地说,static是用于结构体和枚举的静态函数,class是用于类和协议?

这是主要的区别。其他一些不同之处在于类函数是动态分派的,并且可以被子类覆盖。

协议使用class关键字,但它不排除实现协议的结构,而是使用static。Class是为协议选择的,这样就不需要第三个关键字来表示静态或类。

下面是克里斯·拉特纳对这个话题的看法:

我们考虑统一语法(例如使用“type”作为关键字),但这实际上并不能简化事情。关键字“类”和“静态”有助于熟悉并具有相当的描述性(一旦您理解了+方法的工作方式),并为潜在地向类添加真正的静态方法打开了大门。这个模型的主要奇怪之处在于协议必须选择一个关键字(我们选择了“类”),但总的来说,这是正确的权衡。

下面是一个片段,展示了类函数的一些重写行为:

class MyClass {
    class func myFunc() {
        println("myClass")
    }
}

class MyOtherClass: MyClass {
    override class func myFunc() {
        println("myOtherClass")
    }
}

var x: MyClass = MyOtherClass()
x.dynamicType.myFunc() //myOtherClass
x = MyClass()
x.dynamicType.myFunc() //myClass

我在操场上做了一些实验,得到了一些结论。

博士TL;

如您所见,在类的情况下,使用类func还是静态func只是一个习惯问题。

游乐场的例子,并附有解释:

class Dog {
    final func identity() -> String {
        return "Once a woofer, forever a woofer!"
    }

    class func talk() -> String {
        return "Woof woof!"
    }

    static func eat() -> String {
        return "Miam miam"
    }

    func sleep() -> String {
        return "Zzz"
    }
}

class Bulldog: Dog {
    // Can not override a final function
//    override final func identity() -> String {
//        return "I'm once a dog but now I'm a cat"
//    }

    // Can not override a "class func", but redeclare is ok
    func talk() -> String {
        return "I'm a bulldog, and I don't woof."
    }

    // Same as "class func"
    func eat() -> String {
        return "I'm a bulldog, and I don't eat."
    }

    // Normal function can be overridden
    override func sleep() -> String {
        return "I'm a bulldog, and I don't sleep."
    }
}

let dog = Dog()
let bullDog = Bulldog()

// FINAL FUNC
//print(Dog.identity()) // compile error
print(dog.identity()) // print "Once a woofer, forever a woofer!"
//print(Bulldog.identity()) // compile error
print(bullDog.identity()) // print "Once a woofer, forever a woofer!"

// => "final func" is just a "normal" one but prevented to be overridden nor redeclared by subclasses.


// CLASS FUNC
print(Dog.talk()) // print "Woof woof!", called directly from class
//print(dog.talk()) // compile error cause "class func" is meant to be called directly from class, not an instance.
print(Bulldog.talk()) // print "Woof woof!" cause it's called from Bulldog class, not bullDog instance.
print(bullDog.talk()) // print "I'm a bulldog, and I don't woof." cause talk() is redeclared and it's called from bullDig instance

// => "class func" is like a "static" one, must be called directly from class or subclassed, can be redeclared but NOT meant to be overridden.

// STATIC FUNC
print(Dog.eat()) // print "Miam miam"
//print(dog.eat()) // compile error cause "static func" is type method
print(Bulldog.eat()) // print "Miam miam"
print(bullDog.eat()) // print "I'm a bulldog, and I don't eat."

// NORMAL FUNC
//print(Dog.sleep()) // compile error
print(dog.sleep()) // print "Zzz"
//print(Bulldog.sleep()) // compile error
print(bullDog.sleep()) // print "I'm a bulldog, and I don't sleep."