Tôi đã cố gắng tổng hợp vấn đề này xuống dạng đơn giản nhất với những điều sau.
Thiết lập
Phiên bản Xcode 6.1.1 (6A2008a)
Một enum được định nghĩa trong MyEnum.swift
:
internal enum MyEnum: Int {
case Zero = 0, One, Two
}
extension MyEnum {
init?(string: String) {
switch string.lowercaseString {
case "zero": self = .Zero
case "one": self = .One
case "two": self = .Two
default: return nil
}
}
}
và mã mà khởi enum trong tập tin khác, MyClass.swift
:
internal class MyClass {
let foo = MyEnum(rawValue: 0) // Error
let fooStr = MyEnum(string: "zero")
func testFunc() {
let bar = MyEnum(rawValue: 1) // Error
let barStr = MyEnum(string: "one")
}
}
lỗi
Xcode cho tôi lỗi sau khi cố gắng khởi tạo MyEnum
với bộ khởi tạo giá trị thô của nó:
Cannot convert the expression's type '(rawValue: IntegerLiteralConvertible)' to type 'MyEnum?'
Ghi chú
Theo Hướng dẫn ngôn ngữ Swift :
Nếu bạn xác định một kiểu liệt kê có kiểu giá trị thô, kiểu liệt kê sẽ tự động nhận một trình khởi tạo lấy giá trị kiểu của giá trị thô (như một tham số được gọi
rawValue
) và trả về một thành viên liệt kê hoặcnil
.Trình khởi tạo tùy chỉnh cho
MyEnum
được xác định trong một tiện ích mở rộng để kiểm tra xem liệu trình khởi tạo giá trị thô của enum có bị xóa vì trường hợp sau từ Hướng dẫn ngôn ngữ hay không . Tuy nhiên, nó đạt được cùng một kết quả lỗi.Lưu ý rằng nếu bạn xác định bộ khởi tạo tùy chỉnh cho một loại giá trị, bạn sẽ không còn quyền truy cập vào bộ khởi tạo mặc định (hoặc bộ khởi tạo thành viên, nếu nó là một cấu trúc) cho loại đó. [...]
Nếu bạn muốn loại giá trị tùy chỉnh của mình có thể khởi tạo bằng bộ khởi tạo mặc định và bộ khởi tạo thành viên, và cả với bộ khởi tạo tùy chỉnh của riêng bạn, hãy viết bộ khởi tạo tùy chỉnh của bạn trong một tiện ích mở rộng thay vì là một phần của triển khai ban đầu của loại giá trị.Di chuyển định nghĩa enum để
MyClass.swift
giải quyết lỗi chobar
nhưng không chofoo
.Xóa trình khởi tạo tùy chỉnh sẽ giải quyết được cả hai lỗi.
Một cách giải quyết là đưa hàm sau vào định nghĩa enum và sử dụng nó thay cho bộ khởi tạo giá trị thô được cung cấp. Vì vậy, có vẻ như việc thêm trình khởi tạo tùy chỉnh có tác dụng tương tự như đánh dấu trình khởi tạo giá trị thô
private
.init?(raw: Int) { self.init(rawValue: raw) }
Việc khai báo rõ ràng sự tuân thủ của giao thức
RawRepresentable
trongMyClass.swift
giải quyết lỗi nội tuyến chobar
, nhưng dẫn đến lỗi trình liên kết về các ký hiệu trùng lặp (vì các enums kiểu raw-value hoàn toàn phù hợp vớiRawRepresentable
).extension MyEnum: RawRepresentable {}
Bất cứ ai có thể cung cấp thêm một chút thông tin chi tiết về những gì đang xảy ra ở đây? Tại sao không thể truy cập trình khởi tạo giá trị thô?
internal
phạm vi (hoặc ít nhất là phù hợp với loại), khôngprivate
.