วิธีกำหนดค่าคงที่คงที่ในคลาสอย่างรวดเร็ว


105

ฉันมีคำจำกัดความเหล่านี้ในฟังก์ชันที่ใช้งานได้

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

แต่ถ้าฉันย้าย 'testStr' และ 'testStrLen' ไปที่ระดับคลาสมันจะไม่คอมไพล์ มันขึ้นว่า 'MyClass.Type ไม่มีสมาชิกชื่อ' testStr '

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

    func myFunc() {

    }
}

ฉันจะแก้ไขปัญหานี้ได้อย่างไร? ฉันไม่ต้องการจ่ายค่าปรับสำหรับการนับค่าคงที่ของ 'การทดสอบ' ทุกครั้ง

จากความเข้าใจของฉันเกี่ยวกับความคิดเห็นด้านล่างฉันต้องทำสิ่งนี้:

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

    func myFunc() {

    }
}

มีวิธีใดบ้างที่ฉันไม่จำเป็นต้องพิมพ์ / ป้อน "ทดสอบ" สองครั้ง ขอบคุณ.


3
อาจซ้ำกันได้ของViewControl Type ไม่มีสมาชิกที่ชื่อ (ค่าเริ่มต้นของคุณสมบัติไม่สามารถขึ้นอยู่กับคุณสมบัติอื่นได้)
Martin R

1
สามารถทำซ้ำได้ของChange the X และ Y ใน CGRectMake (ด้วยวิธีแก้ปัญหาที่ดีโดยใช้คุณสมบัติขี้เกียจ)
Martin R

"มีวิธีใดบ้างที่ฉันไม่จำเป็นต้องพิมพ์ / ป้อน" ทดสอบ "สองครั้ง" - ใช่ ย้ายการเริ่มต้นของ testStrLen ไปยังวิธีการเริ่มต้น (ตามที่แนะนำในคำตอบสำหรับการทำซ้ำครั้งแรกที่เป็นไปได้) หรือใช้การเริ่มต้นแบบขี้เกียจ (ตามที่แนะนำในคำตอบสำหรับการทำซ้ำครั้งที่สองที่เป็นไปได้)
Martin R

คำตอบ:


177

บางทีสำนวนที่ดีสำหรับการประกาศค่าคงที่สำหรับคลาสใน Swift คือการใช้โครงสร้างชื่อ MyClassConstants ดังต่อไปนี้

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

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

ด้วยวิธีนี้ค่าคงที่ของคุณจะถูกกำหนดขอบเขตภายในโครงสร้างที่ประกาศแทนที่จะลอยไปรอบ ๆ ทั่วโลก

อัปเดต

ฉันได้เพิ่มค่าคงที่อาร์เรย์แบบคงที่เพื่อตอบสนองต่อความคิดเห็นที่ถามเกี่ยวกับการเริ่มต้นอาร์เรย์แบบคงที่ ดูArray Literalsใน "The Swift Programming Language"

สังเกตว่าสามารถใช้ทั้งตัวอักษรสตริงและค่าคงที่สตริงเพื่อเริ่มต้นอาร์เรย์ อย่างไรก็ตามเนื่องจากชนิดอาร์เรย์เป็นที่ทราบกันดีtestStrLengthจึงไม่สามารถใช้ค่าคงที่จำนวนเต็มในตัวเริ่มต้นอาร์เรย์ได้


2
คุณไม่สามารถประกาศค่าคงที่เป็นแบบคงที่ส่วนตัวได้หรือไม่? แล้วพวกเขาจะไม่อยู่ในระดับโลกอีกต่อไปหรือ?
sethfri

3
เต้นโดยใช้. rawValue เหมือนที่ฉันใช้ enum
DogCoffee

1
นี่จะไม่ใช่ทางออกที่ดีที่สุดหากต้องใช้โค้ดจาก Objective C เช่นกันเนื่องจากโครงสร้าง Swift ไม่ได้ถูกแปลเป็น Objective C
mbpro

1
อะไรคือความแตกต่างระหว่างการประกาศstaticค่าคงที่ในStructและในClasses?
Jauzee

1
@YOUNG Swift 2.2 การแจงนับสามารถใช้งานได้ แต่โดยทั่วไปแล้วจะมีการเชื่อมโยงทางความหมายที่แข็งแกร่งกว่าการจัดกลุ่มค่าคงที่โดยทั่วไป ในลิงก์ Swift enums มีทั้งค่าที่เกี่ยวข้องและค่าดิบ คุณสามารถใช้ค่าดิบ แต่ไวยากรณ์คือMyClassConstants.testStr.rawValueการเข้าถึงค่าที่ไม่เป็นมิตร syntactically MyClassConstants.testStrเป็นเพียงแค่
Martin Woolstenhulme

73

กำลังเพิ่มคำตอบของ @ Martin ...

หากใครก็ตามที่วางแผนที่จะเก็บไฟล์คงระดับแอปพลิเคชันไว้คุณสามารถจัดกลุ่มค่าคงที่ตามประเภทหรือลักษณะ

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

โทร : Constants.MixpanelConstants.activeScreen

อัปเดตเดต 5/5/2019 (นอกประเด็น แต่ 🤷🏽‍♂️)

หลังจากอ่านหลักเกณฑ์โค้ดและจากประสบการณ์ส่วนตัวดูเหมือนว่าโครงสร้างไม่ใช่แนวทางที่ดีที่สุดในการจัดเก็บค่าคงที่ทั่วโลกด้วยเหตุผลสองประการ โดยเฉพาะอย่างยิ่งรหัสด้านบนไม่ได้ป้องกันการเริ่มต้นของโครงสร้าง เราสามารถบรรลุได้โดยการเพิ่มรหัสสำเร็จรูป แต่มีแนวทางที่ดีกว่า

ENUMS

สามารถทำได้เช่นเดียวกันโดยใช้ enum ที่มีการแสดงที่ปลอดภัยและชัดเจนยิ่งขึ้น

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

print(Constants.MixpanelConstants.activeScreen.rawValue)

2
ขอบคุณ. ฉันชอบสิ่งนี้เป็นวิธีการจัดการค่าคงที่สวยงามโดยใช้โครงสร้าง
Abhijeet

1
ด้วยตัวอย่างเพิ่มเติมฉันได้เพิ่มแนวทางที่ดีกว่าที่นี่
Anish Parajuli 웃

15

ถ้าฉันเข้าใจคำถามของคุณอย่างถูกต้องคุณกำลังถามว่าคุณจะสร้างค่าคงที่ระดับชั้นเรียนได้อย่างไร (คงที่ - ในภาษา C ++) เพื่อที่คุณจะไม่ a) จำลองค่าโสหุ้ยในทุกๆอินสแตนซ์และ b ต้องคำนวณค่าคงที่อีกครั้ง

ภาษามีการพัฒนา - อย่างที่ผู้อ่านทุกคนรู้ แต่เมื่อฉันทดสอบสิ่งนี้ใน Xcode 6.3.1 วิธีแก้ปัญหาคือ:

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

ฉันไม่รู้ว่าสแตติกมีความจำเป็นอย่างยิ่งเนื่องจากคอมไพเลอร์จะเพิ่มเพียงรายการเดียวต่อตัวแปร const ลงในส่วนคงที่ของไบนารี แต่จะส่งผลต่อไวยากรณ์และการเข้าถึง MyClass.testStrLenโดยใช้แบบคงที่คุณสามารถดูได้แม้ในขณะที่คุณไม่ได้มีอินสแตนซ์:


11

หากคุณต้องการคุณสมบัติคงที่ของชั้นเรียนของคุณสิ่งนี้ยังไม่รองรับใน Swift คำแนะนำในปัจจุบันคือการหลีกเลี่ยงสิ่งนั้นโดยใช้ค่าคงที่ส่วนกลาง:

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

class MyClass {
    func myFunc() {
    }
}

หากคุณต้องการให้สิ่งเหล่านี้เป็นคุณสมบัติของอินสแตนซ์แทนคุณสามารถใช้คุณสมบัติที่จัดเก็บแบบขี้เกียจตามความยาว - จะได้รับการประเมินในครั้งแรกที่เข้าถึงเท่านั้นดังนั้นคุณจะไม่ต้องคำนวณซ้ำแล้วซ้ำอีก

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

    func myFunc() {
    }
}

1
+1 น่าเสียดายที่ยังไม่มีวิธีใดดีไปกว่าตัวแปรระดับโลกเหล่านี้
Drux

1
ฉันรู้ว่านี่เป็นข้อ จำกัด ด้านภาษาในขณะนี้ แต่ฉันอยากจะหลีกเลี่ยงการใช้ globals โดยเสียค่าใช้จ่ายทั้งหมด ฉันคิดว่าการใช้โครงสร้างคอนเทนเนอร์ที่มีบางอย่างเช่น ClassNameConstants น่าจะเป็นแนวทางที่ดีกว่าสำหรับตอนนี้
Zorayr

7

แล้วการใช้คุณสมบัติที่คำนวณได้ล่ะ?

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

MyClass.myConstant

7

บางคนอาจต้องการให้ค่าคงที่ของชั้นเรียนเป็นแบบสาธารณะในขณะที่ค่าคงที่อื่น ๆ เป็นแบบส่วนตัว

คำสำคัญส่วนตัวสามารถใช้เพื่อ จำกัด ขอบเขตของค่าคงที่ภายในไฟล์ที่รวดเร็วเดียวกัน

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

}

ชั้นเรียนอื่น ๆ จะสามารถเข้าถึงค่าคงที่ชั้นเรียนของคุณได้ดังต่อไปนี้

class MyClass2
{

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

} 

2

พยายามใน Playground


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

เกี่ยวข้องกับคำถามนี้อย่างไร?
Franklin Yu
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.