Swift sınıflarındaki statik vs sınıf fonksiyonları/değişkenleri?

Aşağıdaki kod Swift 1.2'de derlenmiştir:

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

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

Statik işlev ile sınıf işlevi arasındaki fark nedir? Hangisini kullanmalıyım, ne zaman?

Başka bir değişken tanımlamaya çalışırsam class var myVar2 = "" , diyor ki:

Sınıfta depolanan özellikler henüz sınıflarda desteklenmiyor; 'statik' mi demek istediniz?

Bu özellik desteklendiğinde, bir statik değişkenle bir sınıf değişkeni arasındaki fark ne olur (yani, her ikisi de bir sınıfta tanımlandığında)? Hangisini kullanmalıyım, ne zaman?

(Xcode 6.3)

332
katma yazar Martin R, kaynak

7 cevap

static and class both associate a method with a class, rather than an instance of a class. The difference is that subclasses can override class methods; they cannot override static methods.

class properties will theoretically function in the same way (subclasses can override them), but they're not possible in Swift yet.

519
katma
@Supuhstar: Temel olarak, evet.
katma yazar mipadi, kaynak
@allenlinli: Aynı şey değiller.
katma yazar mipadi, kaynak
ah, yani Swift'deki statik func foo() {} , Java'daki genel statik final foo() {} gibi mi?
katma yazar Supuhstar, kaynak
Eğer ikisi aynıysa, o zaman aslında “statik” e ihtiyacımız yok?
katma yazar allenlinli, kaynak
@mipadi Şimdi anlıyorum. Sınıf işlevleri için "statik" ifadesini "son sınıf" ile değiştirebiliriz, ancak bir sınıftaki özellikler için, sınıf özellikleri yerine yalnızca statik özelliklere sahip olabiliriz. Yani "statik" anahtar kelime hala onun yerini alıyor.
katma yazar allenlinli, kaynak
"son işlev" sadece "normal" bir ifadedir ancak geçersiz kılınması veya alt sınıflar tarafından yeniden bildirilmesi engellenmiştir.
katma yazar NiravS, kaynak
@hippo_san aynı değil. Kalıtım dalı sayısı sonsuz olabilir. Ve belki bazı dallarda, geçersiz kılmayı kapatmayı ve bazılarını kapatmayı tercih ediyorsunuz - hayır.
katma yazar Mike Glukhov, kaynak
Not sınıf özelliklerine izin verilir, ancak yalnızca sınıflar içinde
katma yazar Jakub Truhlář, kaynak
@hippo_san, bir temel sınıfta ikisi işlevsel olarak aynıdır. Ancak, bir alt sınıfta kullanıldığında daha fazla geçersiz kılmayı kesmek için final kullanılabilir. İkisinin de yeri var, bir sınıf işlevinde kullanıldığında önemsiz ve stil seçiminize göre static veya final kullanımının önemsiz olduğunu söyleyebilirim.
katma yazar Andrew Robinson, kaynak
@mipadi, daha kesin olarak, Swift (şimdilik Swift3'tür) sınıfta depolanan özellikleri desteklememektedir, ancak biri Swift'de hesaplanan sınıf özelliklerini tanımlayabilir.
katma yazar yuchen, kaynak
Öyleyse, bir sınıf içindeki final class işlevi ile 'statik' işlevi arasındaki fark nedir?
katma yazar hippo_san, kaynak

Mipadi'nin cevabını ve oyun alanını yorumladım. Ve paylaşmayı düşündüm. Hadi bakalım. Mipadi'nin cevabının kabul edildiği gibi işaretlenmesi gerektiğini düşünüyorum.

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

    }
}
51
katma

OOP 'a gelince, cevap çok basit:

Alt sınıflar sınıf yöntemlerini geçersiz kılabilir, ancak statik yöntemleri geçersiz kılamaz.

Gönderinize ek olarak, bir sınıf değişkeni bildirmek istiyorsanız ( sınıf var myVar2 = "" yaptığınız gibi), aşağıdaki gibi yapmalısınız:

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

Bu kargaşayı projemden birinde de gördüm ve bu yazıyı çok faydalı buldum. Benim oyun alanında aynı denedim ve işte özeti. Bunun, static , final , class tipindeki, özellikleri geçersiz kılan ve sınıf varyantları vb. Gibi özellikleri ve işlevleri olan birine yardım edeceğini umuyorum.

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"
    }
}

Ve işte test örnekleri:

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
18
katma

Swift 4'te test yapmak, simülatörde performans farkını gösterir. "Class func" ile bir sınıf yaptım ve "static func" ile yapı yaptım ve onları sınava koştum.

statik işlev:

  • 20% faster without compiler optimization
  • 38% faster when optimization -whole-module-optimization is enabled.

Ancak, aynı kodu iPhone 7'de iOS 10.3 altında çalıştırmak tam olarak aynı performansı göstermektedir.

Here is sample project in Swift 4 for Xcode 9 if you like to test yourself https://github.com/protyagov/StructVsClassPerformance

12
katma

Bir fark daha var. class , yalnızca hesaplanan türün tür özelliklerini tanımlamak için kullanılabilir. Bir saklanmış tür özelliğine ihtiyacınız varsa, bunun yerine statik 'ı kullanın.

"Tür özelliklerini statik anahtar sözcükle tanımlıyorsunuz. Hesaplanan tür için sınıf türleri için özellikler yerine, alt sınıfların üst sınıfın uygulamasını geçersiz kılmasına izin vermek için class anahtar sözcüğünü kullanabilirsiniz. "

4
katma

Yukarıdaki cevapların eklenmesi statik yöntemler statik gönderimdir, derleyici, statik yöntem geçersiz kılınamadığı için çalışma zamanında hangi yöntemin uygulanacağını bildiği anlamına gelir; sınıf yöntemi ise alt sınıfın üstesinden gelebileceği gibi dinamik bir gönderim olabilir.

0
katma