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
仅用于类和协议,是否简单?还有其他应该知道的区别吗?在语法本身中具有这种区别的理由是什么?#1 楼
是否仅将static用于结构体和枚举的静态函数,以及用于类和协议的静态类?其他一些区别是类函数是动态分派的,并且可以被子类覆盖。为协议选择了类,因此不必使用第三个关键字来表示static或class。考虑统一语法(例如,使用“ 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
评论
啊哈,非常重要的一点是动态分配类函数!但是你能提供这样的例子吗?您必须将类名写在某个地方,对吗?那么,为什么不静态选择该类的实现呢?
–让-菲利普·佩莱(Jean-Philippe Pellet)
2014年8月6日上午10:10
另一个补充问题:您从哪里获得报价?
–让-菲利普·佩莱(Jean-Philippe Pellet)
2014年8月6日上午10:11
我的理解是,类函数的工作原理与objc +方法完全相同
–康纳
2014年8月6日上午10:14
我可以在这里提供更简单的答案链接吗? stackoverflow.com/questions/29636633/…
– allenlinli
16-4-9的7:42
@ Jean-PhilippePellet在上面的示例中...如果您使用静态函数myFunc()代替类func myFunc,则会收到以下错误l:无法覆盖静态方法。为什么?因为就好像它被标记为final。欲获得更多信息。请参阅下面的nextD的答案。而且x.dynamicType现在也已替换为type(of:x)
–蜂蜜
17年1月16日在2:54
#2 楼
为了更清楚,我在这里举一个例子,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"
}
}
评论
你冠军,很好的答案..我正在寻求这种差异..杰克!
– Abhimanyu Rathore
16年8月17日在11:23
完善。令人印象深刻。
–
16年11月15日在6:48
这应该标记为正确答案。干净整洁!
–abhinavroy23
18年4月1日在17:29
最好的解释!这使我产生了另一个疑问。是否有使用“类功能”的明确理由?我的意思是,如果仅使用“ func”,也可以用相同的方式覆盖它,那么有什么区别?
– Marcos Reboucas
19年7月3日,12:50
@MarcosReboucas如果我正确理解您的问题,则类func与普通func不同,尽管两者都可以被覆盖。但是func用于实例/对象,可以通过ClassA.classFunc()之类的类来访问func类。
–林书豪
19年7月8日在4:57
#3 楼
我在操场上做了一些实验,并得出了一些结论。或class
只是一个习惯问题。带有解释的操场示例:
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."
评论
您的示例没有涵盖另一个答案中提到的主要区别:案例函数的动态分配与静态函数的静态绑定。
–让-菲利普·佩莱(Jean-Philippe Pellet)
16年6月14日在7:06
很好的理解功能的解释。
–尤塞尔·拜勒姆(Yucel Bayram)
16年8月23日在10:52
类函数不是可重写的吗?
–尤利安·奥诺夫雷(Iulian Onofrei)
16年10月10日在21:21
如果您尝试覆盖静态方法,则会出现错误。但是,您可以覆盖类方法。查看已接受的答案
–蜂蜜
17年1月16日在3:03
类func是可重写的。否则我会投票赞成;喜欢研究和榜样!
– Ben Leggiero
17年4月7日在14:03
#4 楼
要声明类型变量属性,请使用
static
声明修饰符标记该声明。类可以使用class
声明修饰符标记类型计算的属性,以允许子类覆盖超类的实现。类型属性在类型属性中讨论。注意
在类声明中,关键字
static
与使用class
和final
声明修饰符标记声明具有相同的作用。来源:Swift编程语言-类型变量属性
评论
问题是关于“静态功能”和“类功能”的问题。它不是在问类型属性。因此,这并不能回答问题-尽管了解这些关键字在属性方面的上下文也很重要。
–etayluz
16-09-21在15:55
这个答案只是在一个错误的问题上,也许是偶然地在这里发布了?
–法蒂
3月5日17:45
#5 楼
根据Apple出版的Swift 2.2书:“您可以通过在方法的func关键字之前编写
static
关键字来指示类型方法。类还可以使用class
关键字来允许子类覆盖该方法的超类实现。” #6 楼
Apple从Swift2.0中说:由类实现时的关键字:“#7 楼
此示例将清除所有方面!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 楼
static和class关键字都允许我们将方法附加到类而不是类的实例。例如,您可以创建一个具有名称和年龄等属性的Student类,然后创建一个由Student类本身而不是单个实例拥有的静态方法numberOfStudents。静态和类不同之处在于它们如何支持继承。当您创建静态方法时,该方法将归该类所有,而不能由子类更改,而当您使用类时,如果需要,可以将其覆盖。
这里是一个示例代码: />
评论
感谢您的回答,但不确定已经提出并获得高度投票的答案的附加价值…
–让-菲利普·佩莱(Jean-Philippe Pellet)
7月7日8:14
#9 楼
这称为类型方法,并使用点语法进行调用,例如实例方法。但是,您在类型上而不是在该类型的实例上调用类型方法。在名为SomeClass的类上调用类型方法的方法如下:评论
class SomeClass {class func someTypeMethod(){//类型方法实现在这里}} SomeClass.someTypeMethod()
–库马尔·乌察夫(Kumar Utsav)
19年1月28日在6:07
这根本无法回答问题。他询问了静态关键字和类关键字之间的区别。
–道格·麦克布赖德(Doug McBride)
19年4月22日在18:31
评论
真的没有区别。我猜他们不能在结构中使用类func,因此不能使用静态func。 struct func将是一个不错的选择。如果您问我,这有点前卫,但那是这些话。那么,还有一个额外的问题:结构可以符合定义类func的协议吗?根据我们现在掌握的信息,这种区分似乎毫无用处,不是吗?
是的你可以。是不是很奇怪?
压倒性的区别是您可以覆盖类函数
需要考虑的是:错误:类方法只允许在类内使用;使用“静态”声明静态方法