Fungsi / variabel statis vs kelas di kelas Swift?


416

Kode berikut dikompilasi di Swift 1.2:

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

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

Apa perbedaan antara fungsi statis dan fungsi kelas ? Yang mana yang harus saya gunakan, dan kapan?

Jika saya mencoba mendefinisikan variabel lain class var myVar2 = "", dikatakan:

Properti tersimpan kelas belum didukung di kelas; maksud Anda 'statis'?

Ketika fitur ini didukung, apa perbedaannya antara variabel statis dan variabel kelas (yaitu ketika keduanya didefinisikan dalam kelas)? Yang mana yang harus saya gunakan, dan kapan?

(Xcode 6.3)


Jawaban:


690

staticdan classkeduanya mengaitkan metode dengan kelas, bukan turunan dari kelas. Perbedaannya adalah bahwa subclass dapat menimpa classmetode; mereka tidak dapat mengganti staticmetode.

class properti secara teoritis akan berfungsi dengan cara yang sama (subclass dapat menimpanya), tetapi mereka belum memungkinkan di Swift.


89
Jadi apa perbedaan antara final classfungsi dan fungsi 'statis' di dalam kelas?
hippo_san

57
@hippo_san, di kelas dasar keduanya secara fungsional sama. Namun, finaldapat digunakan untuk memotong penggantian lebih lanjut saat digunakan dalam subkelas. Keduanya sama-sama memiliki tempat mereka, saya akan mengatakan penggunaan staticatau finalketika digunakan pada fungsi kelas sepele dan hingga pilihan gaya Anda.
Andrew Robinson

8
ah, jadi static func foo(){}di Swift seperti public static final foo(){}di Jawa?
Supuhstar

3
@Supuhstar: Pada dasarnya, ya.
mipadi

2
@mipadi saya mengerti sekarang. Untuk fungsi-fungsi kelas, kita dapat mengganti "statis" dengan "kelas akhir", tetapi untuk properti di kelas, kita hanya dapat memiliki properti statis alih-alih properti kelas. Jadi kata kunci "statis" masih ada tempatnya.
allenlinli

72

Saya mencoba jawaban dan komentar mipadi di taman bermain. Dan berpikir untuk membagikannya. Ini dia Saya pikir jawaban mipadi harus ditandai sebagai diterima.

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

Mengenai OOP , jawabannya terlalu sederhana:

Subclass dapat menimpa metode kelas , tetapi tidak bisa menimpa metode statis .

Selain posting Anda, jika Anda ingin mendeklarasikan variabel kelas (seperti yang Anda lakukan class var myVar2 = ""), Anda harus melakukannya sebagai berikut:

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

23

Saya mendapat kebingungan ini di salah satu proyek saya juga dan menemukan posting ini, sangat membantu. Mencoba hal yang sama di taman bermain saya dan di sini adalah ringkasannya. Semoga ini bisa membantu seseorang dengan sifat dan fungsi yang tersimpan jenis static, final, class, override kelas vars dll

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

Dan di sini adalah sampel pengujian:

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

Pengujian di Swift 4 menunjukkan perbedaan kinerja dalam simulator. Saya membuat kelas dengan "class func" dan struct dengan "static func" dan menjalankannya dalam pengujian.

func statis adalah:

  • 20% lebih cepat tanpa optimasi kompiler
  • 38% lebih cepat ketika optimasi -seluruh-modul-optimasi diaktifkan.

Namun, menjalankan kode yang sama pada iPhone 7 di bawah iOS 10.3 menunjukkan kinerja yang persis sama.

Ini adalah contoh proyek di Swift 4 untuk Xcode 9 jika Anda ingin menguji diri sendiri https://github.com/protyagov/StructVsClassPerformance


apakah ini di simulator atau perangkat fisik?
mmr118


7

Menambahkan ke jawaban di atas metode statis adalah pengiriman statis berarti kompiler tahu metode mana yang akan dieksekusi saat runtime karena metode statis tidak dapat diganti sementara metode kelas dapat menjadi pengiriman dinamis karena subclass dapat menimpanya.


0

Ada satu perbedaan lagi. kelas dapat digunakan untuk mendefinisikan properti tipe dari tipe yang dikomputasi saja. Jika Anda membutuhkan properti tipe simpanan, gunakan yang statis.

Kelas: - tipe referensi

struct: - tipe nilai


0

classdigunakan di dalam Reference Type(kelas):

  • properti yang dihitung
  • metode
  • dapat diganti oleh subclass

staticdigunakan di dalam Reference Typedan Value Type(class, enum):

  • properti yang dihitung dan properti yang disimpan
  • metode
  • tidak dapat diubah dengan subkelas
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

[Referensi vs Tipe Nilai]

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.