Swift'de bir sınıfta statik sabit nasıl tanımlanır


105

İşlevimde çalışan bu tanımlara sahibim

class MyClass {
    func myFunc() {
        let testStr = "test"
        let testStrLen = countElements(testStr)
    }
}

Ancak 'testStr' ve 'testStrLen'i sınıf düzeyine taşırsam, derlenmez. 'MyClass.Type'ın' testStr 'adlı bir üyesi yok yazıyordu.

class MyClass {
    let testStr = "test"
    let testStrLen = countElements(testStr)

    func myFunc() {

    }
}

Bunu nasıl düzeltebilirim? Her seferinde sabit bir 'testin' uzunluğunu saymanın cezasını ödemek istemiyorum.

Aşağıdaki yorumları anladığıma göre, bunu yapmam gerekiyor:

class MyClass {
    let testStr = "test"
    let testStrLen = countElements("test")

    func myFunc() {

    }
}

İki kez "test" yazmamın / girmemin bir yolu var mı? Teşekkürler.


3
ViewControl.Type'ın olası kopyası, adlı bir üyeye sahip değil (Bir özelliğin başlangıç ​​değeri başka bir özelliğe bağlı olamaz.)
Martin R

1
Bir CGRectMake'de X ve Y'yi değiştir'in olası kopyası ( tembel bir özellik kullanarak güzel bir çözümle)
Martin R

"İki kez" test "yazmamın / girmemin bir yolu var mı?" - Evet. TestStrLen'in başlatılmasını bir başlatma yöntemine taşıyın (ilk olası yinelemeye bir yanıtta önerildiği gibi) veya yavaş bir başlatma kullanın (ikinci olası yinelemeye bir yanıtta önerildiği gibi).
Martin R

Yanıtlar:


177

Belki de Swift'deki bir sınıf için sabitleri bildirmek için güzel bir deyim, aşağıdaki gibi MyClassConstants adlı bir yapı kullanmaktır.

struct MyClassConstants{
    static let testStr = "test"
    static let testStrLength = countElements(testStr)

    static let arrayOfTests: [String] = ["foo", "bar", testStr]
}

Bu şekilde, sabitlerinizin kapsamı, küresel olarak gezinmek yerine, bildirilmiş bir yapı içinde olacaktır.

Güncelleme

Statik dizi başlatma hakkında sorulan bir yoruma yanıt olarak statik bir dizi sabiti ekledim. "Swift Programlama Dili" nde Dizi Değişmezlerine bakın .

Diziyi başlatmak için hem dize değişmezlerinin hem de dize sabitinin kullanılabileceğine dikkat edin. Bununla birlikte, dizi türü bilindiğinden, tamsayı sabiti testStrLengthdizi başlatıcıda kullanılamaz.


2
Bunun yerine sabitleri statik özel olarak ilan edemez misiniz? O zaman artık küresel olmazlar mı?
sethfri

3
enum kullanırken .rawValue kullanarak atıyor
DogCoffee

1
Swift yapıları
itibarıyla

1
Es staticiçinde Structve içinde sabitleri bildirmek arasındaki fark nedir Class?
Jauzee

1
@YOUNG Swift 2.2 Numaralandırmalar işe yarayabilir, ancak genel olarak sabitleri gruplamaktan daha güçlü bir semantik ilişkiye sahip numaralandırmalar . Bağlantıda, Swift numaralandırmaları hem ilişkili değerleri hem de ham değerleri içerir. Ham değerleri kullanabilirsiniz, ancak sözdizimi, sözdizimsel MyClassConstants.testStr.rawValueolarak o kadar kolay olmayan değere erişmektir MyClassConstants.testStr.
Martin Woolstenhulme

72

@ Martin'in cevabına ekleniyor ...

Uygulama düzeyinde sabit bir dosya tutmayı planlayan biri varsa, sabiti türüne veya doğasına göre gruplayabilirsiniz.

struct Constants {
    struct MixpanelConstants {
        static let activeScreen = "Active Screen";
    }
    struct CrashlyticsConstants {
        static let userType = "User Type";
    }
}

Aramak : Constants.MixpanelConstants.activeScreen

GÜNCELLEME 5/5/2019 (biraz konu dışı ama 🤷🏽‍♂️)

Bazı kod yönergelerini okuduktan sonra ve kişisel deneyimlerden, birkaç nedenden ötürü küresel sabitleri depolamak için yapılar en iyi yaklaşım değil gibi görünüyor. Özellikle yukarıdaki kod yapının başlatılmasını engellemez. Bunu bazı standart kodlar ekleyerek başarabiliriz ancak daha iyi bir yaklaşım var

ENUMS

Aynı şey, daha güvenli ve net bir temsili olan bir enum kullanılarak da elde edilebilir

enum Constants {
    enum MixpanelConstants: String {
        case activeScreen = "Active Screen";
    }
    enum CrashlyticsConstants: String {
        case userType = "User Type";
    }
}

print(Constants.MixpanelConstants.activeScreen.rawValue)

2
Teşekkür ederim. Bunu beğendim, yapı aracılığıyla sabitleri yönetmek için zarif bir yol sağlar.
Abhijeet

1
Daha fazla örnekle buraya
Anish Parajuli 웃

15

Sorunuzu doğru anladıysam, sınıf düzeyinde sabitleri (statik - C ++ dilinde) nasıl oluşturabileceğinizi soruyorsunuz, öyle ki a) her durumda ek yükü çoğaltmazsınız ve b başka türlü sabit olanı yeniden hesaplamanız gerekir.

Dil gelişti - her okuyucunun bildiği gibi, ancak bunu Xcode 6.3.1'de test ederken çözüm şudur:

import Swift

class MyClass {
    static let testStr = "test"
    static let testStrLen = count(testStr)

    init() {
        println("There are \(MyClass.testStrLen) characters in \(MyClass.testStr)")
    }
}

let a = MyClass()

// -> There are 4 characters in test

Derleyici ikilinin statik bölümüne her const değişkeni için yalnızca bir girdi eklediğinden, statikin kesinlikle gerekli olup olmadığını bilmiyorum, ancak sözdizimini ve erişimi etkiliyor. Bir örneği yok bile statik kullanarak, kendisine başvurabilirsiniz: MyClass.testStrLen.


11

Aslında sınıfınızın statik bir özelliğini istiyorsanız, bu şu anda Swift'de desteklenmiyor. Mevcut tavsiye, küresel sabitleri kullanarak bunu aşmaktır:

let testStr = "test"
let testStrLen = countElements(testStr)

class MyClass {
    func myFunc() {
    }
}

Bunların yerine örnek özellikleri olmasını istiyorsanız , uzun süre saklanan bir özelliği kullanabilirsiniz - yalnızca ilk erişildiğinde değerlendirilir, böylece tekrar tekrar hesaplamazsınız.

class MyClass {
    let testStr: String = "test"
    lazy var testStrLen: Int = countElements(self.testStr)

    func myFunc() {
    }
}

1
+1 Ne yazık ki hala bu küresel değişkenlerden daha iyi bir yol yok gibi görünüyor.
Drux

1
Bunun şu anda bir dil kısıtlaması olduğunu biliyorum, ancak ne pahasına olursa olsun global kullanmaktan kaçınmayı tercih ederim. ClassNameConstants gibi struct container'ları kullanmanın şimdilik daha iyi bir yaklaşım olacağını düşünüyorum.
Zorayr

7

Hesaplanan özellikleri kullanmaya ne dersiniz?

class MyClass {
  class var myConstant: String { return "What is Love? Baby don't hurt me" }
}

MyClass.myConstant

7

Bazıları belirli sınıf sabitlerini kamuya açıkken diğerleri özel olmayı isteyebilir.

private anahtar sözcüğü, aynı hızlı dosyadaki sabitlerin kapsamını sınırlamak için kullanılabilir.

class MyClass {

struct Constants {

    static let testStr = "test"
    static let testStrLen = testStr.characters.count

    //testInt will not be accessable by other classes in different swift files
    private static let testInt = 1
}

func ownFunction()
{

    var newInt = Constants.testInt + 1

    print("Print testStr=\(Constants.testStr)")
}

}

Diğer sınıflar, aşağıdaki gibi sınıf sabitlerinize erişebilecek

class MyClass2
{

func accessOtherConstants()
{
    print("MyClass's testStr=\(MyClass.Constants.testStr)")
}

} 

2

Oyun Alanında Denendi


class MyClass {

struct Constants { static let testStr = "test" static let testStrLen = testStr.characters.count //testInt will not be accessable by other classes in different swift files private static let testInt = 1 static func singletonFunction() { //accessable print("Print singletonFunction testInt=\(testInt)") var newInt = testStrLen newInt = newInt + 1 print("Print singletonFunction testStr=\(testStr)") } } func ownFunction() { //not accessable //var newInt1 = Constants.testInt + 1 var newInt2 = Constants.testStrLen newInt2 = newInt2 + 1 print("Print ownFunction testStr=\(Constants.testStr)") print("Print ownFunction newInt2=\(newInt2)") } } let newInt = MyClass.Constants.testStrLen print("Print testStr=\(MyClass.Constants.testStr)") print("Print testInt=\(newInt)") let myClass = MyClass() myClass.ownFunction() MyClass.Constants.singletonFunction()

Bunun soruyla nasıl bir ilişkisi var?
Franklin Yu
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.