Static vs функции/переменные класса в классах Swift?

Следующий код компилируется в Swift 1.2:

class myClass {
    static func myMethod1() {
    }
    class func myMethod2() {
    }
    static var myVar1 = ""
}

func doSomething() {
    myClass.myMethod1()
    myClass.myMethod2()
    myClass.myVar1 = "abc"
}

В чем разница между функцией static и функцией class? Какой я должен использовать, и когда?

Если я попытаюсь определить другую переменную class var myVar2 = "", она говорит:

Сохраненные свойства класса, еще не поддерживаемые в классах; вы имели в виду "статический"?

Когда эта функция поддерживается, какая разница будет между переменной static и переменной class (т.е. когда оба определены в классе)? Какой я должен использовать, и когда?

(Xcode 6.3)

Ответ 1

static и class связывают метод с классом, а не экземпляр класса. Разница заключается в том, что подклассы могут переопределять методы class; они не могут переопределить методы static.

class свойства будут теоретически функционировать одинаково (подклассы могут их переопределять), но они еще не доступны в Swift.

Ответ 2

Я попробовал ответ mipadi и комментарии на детской площадке. И подумал об этом. Ну вот. Я думаю, что ответ mipadi должен быть отмечен как принятый.

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(){

    }
}

Ответ 3

Что касается ООП, ответ слишком прост:

Подклассы могут переопределять класс методы, но не могут переопределять статические методы.

В дополнение к вашему сообщению, если вы хотите объявить переменную class (как вы это сделали class var myVar2 = ""), вы должны сделать это следующим образом:

class var myVar2: String {
    return "whatever you want"
}

Ответ 4

Я получил эту путаницу в одном из моих проектов, и нашел этот пост, очень полезный. Пробовал то же самое на моей детской площадке, и вот резюме. Надеюсь, это поможет кому-то с сохраненными свойствами и функциями типа static, final, class, переопределением классов vars и т.д.

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

Ответ 5

Тестирование в Swift 4 показывает разницу в производительности в симуляторе. Я создал класс с "класс func" и struct with "static func" и запускал их в тесте.

static func:

  • 20% быстрее без оптимизации компилятора
  • 38% быстрее, когда оптимизация -все-модуль-оптимизация включена.

Однако, запуск того же кода на iPhone 7 под iOS 10.3 показывает точно такую ​​же производительность.

Вот пример проекта в Swift 4 для Xcode 9, если вы хотите испытать себя https://github.com/protyagov/StructVsClassPerformance

Ответ 6

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

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

Ответ 7

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

Ответ 8

Ключевые слова static и class позволяют нам прикреплять переменные к классу, а не к экземплярам класса. Когда к self обращаются в классе, он ссылается на реальный класс (а не на экземпляр).

Переменная

Когда вы создаете static property, он становится владельцем класса и не может быть заменен подклассами, тогда как при использовании class он может быть переопределен при необходимости.

Функция

  • Функции Static не могут быть переопределены. static совпадает с class final
  • Функции Class (не методы экземпляра) также являются статическими функциями, но они отправляются динамически и могут быть переопределены подклассами в отличие от статических функций.
  • Функции Global могут храниться в отдельном файле, который мы можем импортировать в любой проект согласно требованию. В случае функций static, если мы обращаемся к одному из статических членов, весь класс загружается в память. Но в случае функции global только эта конкретная функция будет загружена в память.

Подробнее здесь, здесь