Статические и классовые функции / переменные в классах Swift?
Следующий код компилируется в Swift 1.2:
class myClass {
static func myMethod1() {
}
class func myMethod2() {
}
static var myVar1 = ""
}
func doSomething() {
myClass.myMethod1()
myClass.myMethod2()
myClass.myVar1 = "abc"
}
В чем разница между статической функцией и функцией класса? Какой я должен использовать и когда?
Если я попытаюсь определить другую переменную class var myVar2 = ""
, это говорит:
Свойства классов, которые еще не поддерживаются в классах; Вы имели в виду "статический"?
Когда эта функция поддерживается, какова будет разница между статической переменной и переменной класса (т. Е. Когда они оба определены в классе)? Какой я должен использовать и когда?
(Xcode 6.3)
7 ответов
static
а также class
оба ассоциируют метод с классом, а не с экземпляром класса. Разница в том, что подклассы могут переопределять class
методы; они не могут переопределить static
методы.
class
свойства теоретически будут функционировать одинаково (подклассы могут их переопределять), но в Swift это пока невозможно.
Я попробовал ответ и комментарии Мипади на детской площадке. И думал поделиться этим. Ну вот. Я думаю, что ответ Мипади должен быть отмечен как принятый.
class A{
class func classFunction(){
}
static func staticFunction(){
}
class func classFunctionToBeMakeFinalInImmediateSubclass(){
}
}
class B: A {
override class func classFunction(){
}
//Compile Error. Class method overrides a 'final' class method
override static func staticFunction(){
}
//Lets avoid the function called 'classFunctionToBeMakeFinalInImmediateSubclass' being overriden by subclasses
/* First way of doing it
override static func classFunctionToBeMakeFinalInImmediateSubclass(){
}
*/
// Second way of doing the same
override final class func classFunctionToBeMakeFinalInImmediateSubclass(){
}
//To use static or final class is choice of style.
//As mipadi suggests I would use. static at super class. and final class to cut off further overrides by a subclass
}
class C: B{
//Compile Error. Class method overrides a 'final' class method
override static func classFunctionToBeMakeFinalInImmediateSubclass(){
}
}
Что касается ООП, ответ слишком прост:
Подклассы могут переопределять методы класса, но не могут переопределять статические методы.
В дополнение к вашему посту, если вы хотите объявить переменную класса (как вы это сделали class var myVar2 = ""
), вы должны сделать это следующим образом:
class var myVar2: String {
return "whatever you want"
}
Тестирование в Swift 4 показывает разницу в производительности симулятора. Я создал класс с "class func" и struct с "static func" и запустил их в тесте.
Статическая функция это:
- На 20% быстрее без оптимизации компилятора
- На 38% быстрее, когда включена оптимизация -whole-module-оптимизация.
Однако запуск того же кода на iPhone 7 под iOS 10.3 показывает точно такую же производительность.
Вот пример проекта в Swift 4 для Xcode 9, если вы хотите проверить себя https://github.com/protyagov/StructVsClassPerformance
Я также запутался в одном из моих проектов и нашел этот пост очень полезным. Попробовал то же самое на моей игровой площадке и вот резюме. Надеюсь, что это поможет кому-то с сохраненными свойствами и функциями типа static
, final
,class
, переопределение классов и т. д.
class Simple {
init() {print("init method called in base")}
class func one() {print("class - one()")}
class func two() {print("class - two()")}
static func staticOne() {print("staticOne()")}
static func staticTwo() {print("staticTwo()")}
final func yesFinal() {print("yesFinal()")}
static var myStaticVar = "static var in base"
//Class stored properties not yet supported in classes; did you mean 'static'?
class var myClassVar1 = "class var1"
//This works fine
class var myClassVar: String {
return "class var in base"
}
}
class SubSimple: Simple {
//Successful override
override class func one() {
print("subClass - one()")
}
//Successful override
override class func two () {
print("subClass - two()")
}
//Error: Class method overrides a 'final' class method
override static func staticOne() {
}
//error: Instance method overrides a 'final' instance method
override final func yesFinal() {
}
//Works fine
override class var myClassVar: String {
return "class var in subclass"
}
}
А вот и тестовые образцы:
print(Simple.one())
print(Simple.two())
print(Simple.staticOne())
print(Simple.staticTwo())
print(Simple.yesFinal(Simple()))
print(SubSimple.one())
print(Simple.myStaticVar)
print(Simple.myClassVar)
print(SubSimple.myClassVar)
//Output
class - one()
class - two()
staticOne()
staticTwo()
init method called in base
(Function)
subClass - one()
static var in base
class var in base
class var in subclass
class
используется внутри Reference Type
(класс):
- вычисленное свойство
- метод
- может быть переопределен подклассом
static
используется внутри Reference Type
а также Value Type
(класс, перечисление):
- вычисляемое свойство и сохраненное свойство
- метод
- не может быть изменен подклассом
protocol MyProtocol {
// class var protocolClassVariable : Int { get }//ERROR: Class properties are only allowed within classes
static var protocolStaticVariable : Int { get }
// class func protocolClassFunc()//ERROR: Class methods are only allowed within classes
static func protocolStaticFunc()
}
struct ValueTypeStruct: MyProtocol {
//MyProtocol implementation begin
static var protocolStaticVariable: Int = 1
static func protocolStaticFunc() {
}
//MyProtocol implementation end
// class var classVariable = "classVariable"//ERROR: Class properties are only allowed within classes
static var staticVariable = "staticVariable"
// class func classFunc() {} //ERROR: Class methods are only allowed within classes
static func staticFunc() {}
}
class ReferenceTypeClass: MyProtocol {
//MyProtocol implementation begin
static var protocolStaticVariable: Int = 2
static func protocolStaticFunc() {
}
//MyProtocol implementation end
var variable = "variable"
// class var classStoredPropertyVariable = "classVariable"//ERROR: Class stored properties not supported in classes
class var classComputedPropertyVariable: Int {
get {
return 1
}
}
static var staticStoredPropertyVariable = "staticVariable"
static var staticComputedPropertyVariable: Int {
get {
return 1
}
}
class func classFunc() {}
static func staticFunc() {}
}
final class FinalSubReferenceTypeClass: ReferenceTypeClass {
override class var classComputedPropertyVariable: Int {
get {
return 2
}
}
override class func classFunc() {}
}
//class SubFinalSubReferenceTypeClass: FinalSubReferenceTypeClass {}// ERROR: Inheritance from a final class
Есть еще одно отличие. class
может использоваться для определения свойств типа только для вычисляемого типа. Если вам нужно свойство сохраненного типа, используйте static
вместо.
Добавление к вышеупомянутым ответам статических методов - статическая диспетчеризация - означает, что компилятор знает, какой метод будет выполнен во время выполнения, поскольку статический метод не может быть переопределен, в то время как метод класса может быть динамической диспетчеризацией, поскольку подкласс может переопределить их.
Есть еще одно отличие. class может использоваться для определения свойств типа только вычисляемого типа. Если вам нужно свойство хранимого типа, используйте вместо него static.
Класс:- ссылочный тип
struct:- тип значения