Cách xác định hằng số tĩnh trong một lớp nhanh chóng


105

Tôi có những định nghĩa này trong chức năng của tôi, nó hoạt động

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

Nhưng nếu tôi chuyển 'testStr' và 'testStrLen' lên cấp lớp, nó sẽ không biên dịch. Nó cho biết 'MyClass.Type không có thành viên có tên' testStr '.

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

    func myFunc() {

    }
}

Làm thế nào tôi có thể sửa lỗi này? Tôi không muốn bị phạt vì luôn luôn đếm len của một 'bài kiểm tra' liên tục.

Dựa trên hiểu biết của tôi về các nhận xét bên dưới, tôi cần thực hiện điều này:

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

    func myFunc() {

    }
}

Có cách nào tôi không cần gõ / nhập "test" hai lần không? Cảm ơn.


3
có thể trùng lặp của ViewControl.Type không có một thành viên mang tên (Giá trị ban đầu của một tài sản không thể phụ thuộc vào bất động sản khác.)
Martin R

1
có thể trùng lặp của Change X và Y trong một CGRectMake (với một giải pháp tốt đẹp sử dụng một tài sản lười biếng)
Martin R

"Có cách nào tôi không cần gõ / nhập" test "hai lần không?" - Đúng. Di chuyển quá trình khởi tạo testStrLen vào một phương thức init (như được đề xuất trong câu trả lời cho bản sao có thể có đầu tiên) hoặc sử dụng khởi tạo lười biếng (như được đề xuất trong câu trả lời cho bản sao có thể thứ hai).
Martin R

Câu trả lời:


177

Có lẽ một thành ngữ hay để khai báo hằng số cho một lớp trong Swift là chỉ sử dụng một cấu trúc có tên MyClassConstants như sau.

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

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

Bằng cách này, hằng số của bạn sẽ được xác định phạm vi trong một cấu trúc đã khai báo thay vì trôi nổi trên toàn cục.

Cập nhật

Tôi đã thêm một hằng số mảng tĩnh, để trả lời một nhận xét hỏi về việc khởi tạo mảng tĩnh. Xem Array Literals trong "Ngôn ngữ lập trình Swift".

Lưu ý rằng cả chuỗi ký tự và hằng chuỗi đều có thể được sử dụng để khởi tạo mảng. Tuy nhiên, vì kiểu mảng đã biết nên testStrLengthkhông thể sử dụng hằng số nguyên trong bộ khởi tạo mảng.


2
Thay vào đó, bạn có thể không chỉ khai báo các hằng số là static private? Không phải sau đó họ sẽ không còn là toàn cầu nữa?
sethfri

3
đánh bại bằng cách sử dụng .rawValue như tôi đang sử dụng enum
DogCoffee

1
Đây sẽ không phải là giải pháp tốt nhất nếu mã được sử dụng từ Objective C là tốt, vì Swift cấu trúc không được dịch sang Objective C
mbpro

1
Sự khác biệt giữa khai báo statichằng trong Structvà trong Classes là gì?
Jauzee

1
@YOUNG Swift 2.2 Các phép liệt kê có thể hoạt động, nhưng thường bao hàm việc có liên kết ngữ nghĩa mạnh mẽ hơn là chỉ nhóm các hằng số nói chung. Trong liên kết, Swift enums có cả giá trị được kết hợp và giá trị thô. Bạn có thể sử dụng các giá trị thô, nhưng cú pháp là MyClassConstants.testStr.rawValueđể truy cập giá trị, nó không thân thiện về mặt cú pháp MyClassConstants.testStr.
Martin Woolstenhulme

72

Thêm vào câu trả lời của @ Martin ...

Nếu bất kỳ ai định giữ tệp không đổi ở mức ứng dụng, bạn có thể nhóm hằng số dựa trên loại hoặc bản chất của chúng

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

Gọi : Constants.MixpanelConstants.activeScreen

CẬP NHẬT 5/5/2019 (hơi lạc đề nhưng 🤷🏽‍♂️)

Sau khi đọc một số hướng dẫn về mã và từ kinh nghiệm cá nhân, có vẻ như cấu trúc không phải là cách tiếp cận tốt nhất để lưu trữ các hằng số toàn cầu vì một vài lý do. Đặc biệt là đoạn mã trên không ngăn cản việc khởi tạo cấu trúc. Chúng ta có thể đạt được điều đó bằng cách thêm một số đoạn mã soạn sẵn nhưng có một cách tiếp cận tốt hơn

ENUMS

Điều tương tự cũng có thể đạt được bằng cách sử dụng một enum với biểu diễn rõ ràng và an toàn hơn

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

print(Constants.MixpanelConstants.activeScreen.rawValue)

2
Cảm ơn bạn. Tôi thích điều này, cung cấp một cách quản lý hằng số thông qua struct.
Abhijeet

1
Với nhiều ví dụ hơn, tôi đã thêm một cách tiếp cận tốt hơn ở đây
Anish Parajuli 웃

15

Nếu tôi hiểu câu hỏi của bạn một cách chính xác, bạn đang hỏi làm thế nào bạn có thể tạo hằng số cấp độ lớp (tĩnh - theo cách nói của C ++) sao cho bạn không a) sao chép chi phí trong mọi trường hợp và b phải tính toán lại những gì là hằng số.

Ngôn ngữ đã phát triển - như mọi người đọc đều biết, nhưng khi tôi kiểm tra điều này trong Xcode 6.3.1, giải pháp là:

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

Tôi không biết liệu tĩnh có thực sự cần thiết hay không vì trình biên dịch chắc chắn chỉ thêm một mục nhập cho mỗi biến const vào phần tĩnh của tệp nhị phân, nhưng nó ảnh hưởng đến cú pháp và quyền truy cập. Bằng cách sử dụng tĩnh, bạn có thể tham khảo nó ngay cả khi bạn không có một thể hiện: MyClass.testStrLen.


11

Nếu bạn thực sự muốn một thuộc tính tĩnh của lớp mình, thuộc tính đó hiện không được hỗ trợ trong Swift. Lời khuyên hiện tại là giải quyết vấn đề đó bằng cách sử dụng các hằng số toàn cục:

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

class MyClass {
    func myFunc() {
    }
}

Thay vào đó, nếu bạn muốn những thuộc tính này là thuộc tính cá thể, bạn có thể sử dụng thuộc tính được lưu trữ lười biếng cho độ dài - nó sẽ chỉ được đánh giá lần đầu tiên được truy cập, vì vậy bạn sẽ không phải tính toán nhiều lần.

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

    func myFunc() {
    }
}

1
+1 Thật tệ, dường như vẫn không có cách nào tốt hơn những biến toàn cục này.
Drux

1
Tôi biết đây là một hạn chế về ngôn ngữ vào lúc này, nhưng tôi thà tránh sử dụng toàn cầu bằng mọi giá. Tôi nghĩ rằng sử dụng các thùng chứa cấu trúc w / một cái gì đó như ClassNameConstants sẽ là một cách tiếp cận tốt hơn cho bây giờ.
Zorayr

7

Điều gì về việc sử dụng các thuộc tính được tính toán?

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

MyClass.myConstant

7

Một số có thể muốn các hằng số lớp nhất định là công khai trong khi những hằng số khác ở chế độ riêng tư.

Từ khóa private có thể được sử dụng để giới hạn phạm vi của các hằng số trong cùng một tệp nhanh.

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

}

Các lớp khác sẽ có thể truy cập các hằng số lớp của bạn như bên dưới

class MyClass2
{

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

} 

2

Đã thử trên 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()

Làm thế nào điều này có liên quan đến câu hỏi?
Franklin Yu
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.