Когда использовать статическую константу и переменную в Swift?

Есть несколько сообщений о том, как писать код для static constant и static variable в Swift. Но неясно, когда использовать static constant и static variable а не constant и variable. Может кто-нибудь объяснить?

Ответ 1

Когда вы определяете статический var/let в классе (или структуре), эта информация будет использоваться для всех экземпляров (или значений).

Обмен информацией

class Animal {
    static var nums = 0

    init() {
        Animal.nums += 1
    }
}

let dog = Animal()
Animal.nums // 1
let cat = Animal()
Animal.nums // 2

Как вы можете видеть здесь, я создал 2 отдельных экземпляра Animal но оба они используют одну и ту же статическую переменную nums.

одиночка

Часто статическая константа используется для принятия шаблона Singleton. В этом случае мы хотим выделить не более одного экземпляра класса. Для этого мы сохраняем ссылку на общий экземпляр внутри константы, и мы скрываем инициализатор.

class Singleton {
    static let sharedInstance = Singleton()

    private init() { }

    func doSomething() { }
}

Теперь, когда нам нужен экземпляр Singleton мы пишем

Singleton.sharedInstance.doSomething()
Singleton.sharedInstance.doSomething()
Singleton.sharedInstance.doSomething()

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

Ответ 2

Есть несколько сообщений о том, как писать код для статической константы и статической переменной в Swift. Но неясно, когда использовать статическую константу и статическую переменную, а не константу и переменную. Может кто-нибудь объяснить? Когда вы определяете статический var/let в класс (или struct), это значение будет использоваться для всех экземпляров (или значений).

статические переменные/класс - это переменные, которые могут быть доступны без необходимости создания какого-либо экземпляра/объекта.

class Human {
    static let numberOfEyes = 2 //human have only 2 eyes
    static var eyeDefect = false //whether human have side-effect or not. he can have defect later so its variable

    //other variables and functions
}

//you can access numberOfEyes like below no object of Human is created
print(Human.numberOfEyes)
print(Human.eyeDefect)

//Object of Human
let john = Human()

Я думаю, вы знаете разницу между константой и переменной. Короче говоря, константа такова, что ее значение никогда не меняется; numberOfEyes в приведенном выше примере и переменной - это значение, значение которого изменяется; eyeDefect в приведенном выше примере.

статическая константа или переменные помещаются в память (ОЗУ) отдельно, а затем объекты. т.е. numberOfEyes имеют другое пространство памяти, выделенное, чем объект Джона, его не внутри Джона.

теперь, когда использовать статические константы/переменные:

  1. Когда вы используете шаблон модели singleton: static let sharedInstance = APIManager()

    class APIManager(){
        static let sharedInstance = APIManager()
        //Your other variables/functions here below
    }
    //Use it as to get singleton instance of APIManager from anywhere in your application
    let instanceOfAPIManager = APIManager.sharedInstance
    
  2. Когда вам нужна ценность чего-либо, что глобально одинаково, без необходимости создавать экземпляр класса, в котором он определен как numberOfEyes в человеческом классе.

  3. Использование статических переменных/констант мало рекомендуется из-за проблем с памятью, потому что после его создания/назначения он остается в памяти, пока ваше приложение не будет удалено из памяти. Я нашел до сих пор лучшее место для использования статических переменных/констант только при создании одноэлементного шаблона, а иногда указатели на другие нормальные переменные и константы не используют статические, потому что: проблема с памятью, будет сложно запустить модульное тестирование в вашем коде со статическими переменными/константами. Не рекомендуется использовать как в человеческом классе. вместо этого используйте их как просто постоянные или переменные и обращайтесь к ним путем создания экземпляра.

    class Human {
     let numberOfEyes = 2 //human have only 2 eyes
     var eyeDefect = false //whether human have side-effect or not. he can have defect later so its variable
    
       //other variables and functions
     }
    
    //you can access numberOfEyes like below if you need just those values.
    print(Human().numberOfEyes)
    print(Human().eyeDefect)
    

Ответ 3

Статические константы и переменные принадлежат самому классу, а не конкретному экземпляру. Класс также может иметь статические методы, которые можно вызывать без создания экземпляра класса.

Поэтому, когда у вас есть класс MyClass со статическим var x, вы также можете получить к нему доступ через MyClass.x напрямую. x будет использоваться для всех экземпляров класса

Ответ 4

Это более важный комментарий:

class Person {
    static var name = "Static John" // a property of Person 'type'
    var name = "Alex" // a property of Person 'instance'

    var nonStaticName = "Peter"
    static var staticName = "Sara"



    static func statFunc() {
        let x = Person.name // Static John
        let y = name // Static John or Alex?!  Static John!!!!
        let r = staticName // Sara
        let k = nonStaticName // ERROR: instance member 'nonStaticName' cannot be used on type 'Person'
        // The compiler is like: I'm referrting to the 'nonStaticName' property of which instance?! There is no instance! Sorry can't do!

    }

    func nonStaticFunc() {
        let x = Person.name // Static John
        let y = name // Static John or Alex?! Alex!!! Because we're in a instance scope...
        let k = nonStaticName // Obviously works
        let r = staticName // ERROR: static member 'staticName' cannot be used on instance of type 'Person'. Person.staticName will work
    }
}

Интересные наблюдения:

Первый:

static var name = "Static John" // a property of Person 'type'
var name = "Alex" // a property of Person 'instance'

не создает конфликтов.

Во- вторых:

Вы никогда не можете использовать переменные экземпляра внутри статических переменных. Вы можете использовать статические переменные внутри функций экземпляра, если вы ссылаетесь на него, Person.name к нему префикс типа, т.е. делайте Person.name, тогда как

статические переменные могут быть доступны внутри статических функций с префиксом типа или без него, т.е. Person.staticName или staticName работают.