Когда использовать статическую константу и переменную в 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 имеют другое пространство памяти, выделенное, чем объект Джона, его не внутри Джона.
теперь, когда использовать статические константы/переменные:
-
Когда вы используете шаблон модели 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
-
Когда вам нужна ценность чего-либо, что глобально одинаково, без необходимости создавать экземпляр класса, в котором он определен как numberOfEyes в человеческом классе.
-
Использование статических переменных/констант мало рекомендуется из-за проблем с памятью, потому что после его создания/назначения он остается в памяти, пока ваше приложение не будет удалено из памяти. Я нашел до сих пор лучшее место для использования статических переменных/констант только при создании одноэлементного шаблона, а иногда указатели на другие нормальные переменные и константы не используют статические, потому что: проблема с памятью, будет сложно запустить модульное тестирование в вашем коде со статическими переменными/константами. Не рекомендуется использовать как в человеческом классе. вместо этого используйте их как просто постоянные или переменные и обращайтесь к ним путем создания экземпляра.
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
работают.