What is the difference between static func and class func in Swift?
我可以在Swift库中看到这些定义:
1 2 3 4 5 6 7 8 | extension Bool : BooleanLiteralConvertible { static func convertFromBooleanLiteral(value: Bool) -> Bool } protocol BooleanLiteralConvertible { typealias BooleanLiteralType class func convertFromBooleanLiteral(value: BooleanLiteralType) -> Self } |
定义为
Is it simply that static is for static functions of structs and enums, and class for classes and protocols?
这就是主要的区别。还有一些区别是类函数是动态调度的,可以被子类覆盖。
协议使用class关键字,但它不排除实现协议的结构,而是使用static。类是为协议选择的,因此不必有第三个关键字来表示静态或类。
Chris Lattner关于这个话题:
We considered unifying the syntax (e.g. using"type" as the keyword), but that doesn't actually simply things. The keywords"class" and"static" are good for familiarity and are quite descriptive (once you understand how + methods work), and open the door for potentially adding truly static methods to classes. The primary weirdness of this model is that protocols have to pick a keyword (and we chose"class"), but on balance it is the right tradeoff.
下面是一个片段,展示了类函数的一些重写行为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class ClassA { class func func1() -> String { return"func1" } static func func2() -> String { return"func2" } /* same as above final class func func2() -> String { return"func2" } */ } |
因为它是
1 2 3 4 5 6 7 8 9 10 | 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" } } |
我在操场上做了一些实验,得出了一些结论。
DR
如你所见,在
带解释的操场示例:
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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | 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." |
To declare a type variable property, mark the declaration with the
static declaration modifier. Classes may mark type computed properties with theclass declaration modifier instead to allow subclasses to override the superclass’s implementation. Type properties are discussed in Type Properties.NOTE
In a class declaration, the keywordstatic has the same effect as marking the declaration with both theclass andfinal declaration modifiers.< /块引用>
来源:Swift编程语言-类型变量属性
根据苹果出版的Swift 2.2书:
"通过在方法的func关键字之前写入
static 关键字,可以指示类型方法。类也可以使用class 关键字来允许子类重写超类对该方法的实现。"从Swift2.0,苹果说:
"在协议中定义类型属性要求时,请始终使用静态关键字作为前缀。此规则适用,即使类型属性要求在由类实现时可以以类或静态关键字作为前缀:"
这称为类型方法,并使用点语法(如实例方法)调用。但是,可以对该类型调用类型方法,而不是对该类型的实例调用类型方法。以下是如何在名为SomeClass的类上调用类型方法:
主要区别在于结构是值类型,类是引用类型。
当您复制一个值类型时,它会将您要复制的对象中的所有数据复制到新变量中。它们是两个分开的东西,改变一个不会影响另一个。
复制引用类型时,新变量引用的内存位置与正在复制的内容相同。这意味着改变一个会改变另一个,因为它们都指向相同的内存位置。