Swift sınıflarında statik ve sınıf işlevleri / değişkenleri?


416

Swift 1.2'de aşağıdaki kod derlenir:

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 ve ne zaman kullanmalıyım?

Başka bir değişken tanımlamaya çalışırsam class var myVar2 = ""şöyle der:

Sınıfta saklanan özellikler henüz sınıflarda desteklenmez; "statik" mi demek istediniz?

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

(Xcode 6.3)


Yanıtlar:


690

staticve classher ikisi de bir yöntemi sınıf örneği yerine sınıfla ilişkilendirir. Fark, alt sınıfların classyöntemleri geçersiz kılabilmesidir; staticyöntemleri geçersiz kılamazlar .

class özellikler teorik olarak aynı şekilde çalışır (alt sınıflar bunları geçersiz kılabilir), ancak Swift'te henüz mümkün değildir.


89
Öyleyse final classbir sınıf içindeki işlev ve 'statik' işlev arasındaki fark nedir?
hippo_san

57
@hippo_san, bir temel sınıfta ikisi işlevsel olarak aynıdır. Ancak, finalbir alt sınıfta kullanıldığında diğer geçersiz kılmaları kesmek için kullanılabilir. İkisinin de yeri var, bir sınıf fonksiyonunun kullanımı staticveya finalkullanıldığında önemsiz ve stil seçiminize kadar diyebilirim .
Andrew Robinson

8
Ah, yani static func foo(){}Swift'te public static final foo(){}Java'daki gibi mi?
Supuhstar

3
@Supuhstar: Temel olarak evet.
mipadi

2
@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. "Statik" anahtar kelimenin yeri hala var.
allenlinli

72

Mipadi'nin oyun alanı hakkındaki cevabını ve yorumlarını denedim. Ve paylaşmayı düşündüm. Hadi bakalım. Bence mipadi'nin cevabı kabul edilmiş olarak işaretlenmeli.

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

OOP ile ilgili olarak , cevap çok basit:

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

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

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

23

Bu karışıklığı projemden birinde de aldım ve bu gönderiyi çok yararlı buldum. Oyun alanımda da aynı şeyi denedim ve işte özeti. Bu depolanan özelliklerin ve tip fonksiyonları olan biri yardımcı olur umarım static, final, class, geçersiz kılma sınıf vars vb

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 burada 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

23

Swift 4'te test yapmak, simülatördeki performans farkını gösterir. Ben "class func" ile bir sınıf ve "statik func" ile yapı ve onları test koştu.

statik işlev:

  • Derleyici optimizasyonu olmadan % 20 daha hızlı
  • Optimizasyon -tüm modül-optimizasyon etkinleştirildiğinde % 38 daha hızlı.

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

Kendinizi test etmek isterseniz Swift 4'te Xcode 9 için örnek proje: https://github.com/protyagov/StructVsClassPerformance


bu simülatörde veya fiziksel cihazda mıydı?
mmr118


7

Yukarıdaki yanıtlara statik yöntemlerin eklenmesi statik dağıtımdır, derleyici çalışma zamanında hangi yöntemin yürütüleceğini bilir, çünkü sınıf yöntemi, alt sınıf bunları geçersiz kılabileceğinden, statik yöntem geçersiz kılınamaz.


0

Bir fark daha var. sınıfı yalnızca hesaplanan türün tür özelliklerini tanımlamak için kullanılabilir. Depolanmış bir type özelliğine ihtiyacınız varsa bunun yerine static kullanın.

Sınıf: - referans türü

struct: - değer türü


0

classiçinde kullanılır Reference Type(sınıf):

  • hesaplanmış mülkiyet
  • yöntem
  • olabilir alt sınıf tarafından geçersiz kılınabilir

staticiçinde kullanılır Reference Typeve Value Type(class, enum):

  • hesaplanmış özellik ve depolanmış özellik
  • yöntem
  • olamaz alt sınıf tarafından değiştirilebilir
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

[Referans ve Değer Türüne Karşı]

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.