Статические и классовые функции / переменные в классах 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 вместо.

"Вы определяете свойства типов с помощью ключевого слова static. Для вычисляемых свойств типов для типов классов вместо этого вы можете использовать ключевое слово class, чтобы подклассы могли переопределить реализацию суперкласса".

Добавление к вышеупомянутым ответам статических методов - статическая диспетчеризация - означает, что компилятор знает, какой метод будет выполнен во время выполнения, поскольку статический метод не может быть переопределен, в то время как метод класса может быть динамической диспетчеризацией, поскольку подкласс может переопределить их.

Есть еще одно отличие. class может использоваться для определения свойств типа только вычисляемого типа. Если вам нужно свойство хранимого типа, используйте вместо него static.

Класс:- ссылочный тип

struct:- тип значения

Другие вопросы по тегам