我可以在Swift库中看到这些定义:
extension Bool : BooleanLiteralConvertible {
static func convertFromBooleanLiteral(value: Bool) -> Bool
}
protocol BooleanLiteralConvertible {
typealias BooleanLiteralType
class func convertFromBooleanLiteral(value: BooleanLiteralType) -> Self
}
定义为static func
的成员函数与定义为class func
的另一成员函数之间的区别是什么?只是static
用于结构和枚举的静态函数,class
用于类和协议吗?还有其他人应该知道的差异吗?在语法本身中有这种区别的理由是什么?
答案 0 :(得分:194)
对于结构和枚举的静态函数,以及类和协议的类,是静态吗?
这是主要的区别。其他一些差异是类函数是动态调度的,可以被子类覆盖。
协议使用class关键字,但它不会排除结构实现协议,而只是使用static。为协议选择了类,因此不必使用第三个关键字来表示静态或类。
来自Chris Lattner关于这个话题:
我们考虑统一语法(例如使用“type”作为关键字),但实际上并不是简单的事情。关键字“class”和“static”有助于熟悉并且非常具有描述性(一旦理解了+方法的工作原理),并为可能向类添加真正的静态方法打开了大门。这个模型的主要奇怪之处在于协议必须选择一个关键字(我们选择“类”),但总的来说这是正确的权衡。
这是一个片段,显示了类函数的一些覆盖行为:
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
答案 1 :(得分:189)
为了更清楚,我在这里举个例子,
class ClassA {
class func func1() -> String {
return "func1"
}
static func func2() -> String {
return "func2"
}
/* same as above
final class func func2() -> String {
return "func2"
}
*/
}
static func
与final class 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"
}
}
答案 2 :(得分:63)
我在操场上做了一些实验并得出了一些结论。
正如您所见,在class
的情况下,使用class func
或static 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."
答案 3 :(得分:51)
要声明类型变量属性,请使用
static
声明修饰符标记声明。类可以使用class
声明修饰符标记类型计算属性,以允许子类覆盖超类的实现。类型属性在类型属性中讨论。注
在类声明中,关键字static
与使用class
和final
声明修饰符标记声明具有相同的效果。
来源:The Swift Programming Language - Type Variable Properties
答案 4 :(得分:13)
根据苹果公布的Swift 2.2 Book:
“通过在方法的func关键字之前写static
关键字来指示类型方法。类也可以使用class
关键字来允许子类覆盖超类的该方法的实现。“
答案 5 :(得分:10)
从Swift2.0开始,Apple说:
“在协议中定义类型属性要求时,请始终使用static关键字作为前缀类型属性要求。即使类型属性要求在类实现时可以使用类或静态关键字作为前缀,该规则也适用:”
答案 6 :(得分:1)
通过 static 和 class 关键字,我们可以将方法附加到类上,而不是附加到类的实例上。例如,您可以创建一个具有名称和年龄等属性的Student类,然后创建一个由Student类本身而非单个实例拥有的静态方法numberOfStudents。
静态和类的不同之处在于它们支持继承的方式。当您创建静态方法时,该方法将归该类所有,并且不能由子类更改,而当您使用类时,如果需要,它可能会被覆盖。
这是示例代码:
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
}
}
答案 7 :(得分:0)
该示例将清除所有方面!
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.
*/
答案 8 :(得分:-2)
这称为类型方法,并使用点语法(如实例方法)进行调用。但是,您在类型上而不是在该类型的实例上调用类型方法。在名为SomeClass的类上调用类型方法的方法如下:
答案 9 :(得分:-8)
主要区别在于结构是值类型,类是引用类型。
当您复制值类型时,它会将您要复制的内容中的所有数据复制到新变量中。它们是两个单独的东西,而改变一个不会影响另一个
制作引用类型的副本时,新变量引用与要复制的内容相同的内存位置。这意味着更改一个将更改另一个,因为它们都指向相同的内存位置