Статичні функції / зміни класу в класах Swift?


416

У 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)


Відповіді:


690

staticі classобидва асоціюють метод із класом, а не екземпляром класу. Різниця полягає в тому, що підкласи можуть змінювати classметоди; вони не можуть перекрити staticметоди.

class Властивості теоретично будуть функціонувати так само (підкласи можуть їх перекрити), але в Swift поки що це неможливо.


89
Отже, в чому різниця між final classфункцією та "статичною" функцією в класі?
hippo_san

57
@hippo_san, в базовому класі ці функціонально однакові. Однак finalможе використовуватися для відсічення подальших переосмислень при використанні підкласу. Обидва мають своє місце, я б сказав, що використання staticабо finalколи використовується у класовій функції тривіально і залежить від вашого вибору стилю.
Ендрю Робінсон

8
ах, значить, static func foo(){}у Swift це як public static final foo(){}на Яві?
Supuhstar

3
@Supuhstar: В основному, так.
mipadi

2
@mipadi Я зараз розумію. Для функцій класу ми можемо замінити "статичний" на "остаточний клас", але для властивостей класу ми можемо мати лише статичні властивості замість властивостей класу. Тож "статичне" ключове слово все ще має своє місце.
allenlinli

72

Я спробував відповідь і коментарі 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(){

    }
}

27

Що стосується ООП , то відповідь занадто проста:

Підкласи можуть переосмислювати методи класу , але не можуть перекривати статичні .

На додаток до своєї публікації, якщо ви хочете оголосити змінну класу (як і ви class var myVar2 = ""), слід зробити це так:

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

23

Я також заплутався в одному зі своїх проектів і знайшов цю публікацію дуже корисною. Спробував те ж саме на моєму майданчику і ось підсумок. Сподіваюся , що це допомагає хто - то з зберігаються властивостями і функціями типу 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

23

Тестування в Swift 4 показує різницю продуктивності в тренажері. Я склав клас з "class func" та структура з "static func" і провів їх у тесті.

статичний функціонал:

  • На 20% швидше без оптимізації компілятора
  • На 38% швидше, коли ввімкнено оптимізацію -оптимальний модуль.

Однак запуск того самого коду на iPhone 7 під iOS 10.3 демонструє абсолютно таку ж продуктивність.

Ось зразок проекту у Swift 4 для Xcode 9, якщо ви хочете протестувати себе https://github.com/protyagov/StructVsClassPerformance


це було на тренажері чи фізичному пристрої?
mmr118

7

Є ще одна різниця. classможна використовувати лише для визначення властивостей типу обчисленого типу . Якщо вам потрібно використовувати властивість збереженого типуstatic .

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


7

Додавання до вищезазначених відповідей статичних методів є статичним відправленням означає, що компілятор знає, який метод буде виконуватися під час виконання, оскільки статичний метод не може бути замінений, тоді як метод класу може бути динамічним відправленням, оскільки підклас може їх замінити.


0

Є ще одна різниця. клас можна використовувати лише для визначення властивостей типу обчисленого типу. Якщо вам потрібна властивість збереженого типу, використовуйте статичний натомість.

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

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


0

classвикористовується всередині Reference Type(клас):

  • обчислене майно
  • метод
  • може бути замінено підкласом

staticвикористовується всередині Reference Typeта Value Type(class, enum):

  • обчислене майно та збережене майно
  • метод
  • не може бути змінено підкласом
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

[Посилання порівняння зі значенням]

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.