Một phép liệt kê xác định một kiểu chung cho một nhóm các giá trị có liên quan và cho phép bạn làm việc với các giá trị đó theo cách an toàn kiểu trong mã của bạn Nếu bạn đã quen thuộc với C, bạn sẽ biết rằng kiểu liệt kê trong C gán các tên liên quan cho một tập hợp các giá trị số nguyên. Phép liệt kê trong Swift linh hoạt hơn nhiều và không phải cung cấp giá trị cho từng trường hợp của phép liệt kê. Nếu một giá trị (được gọi là giá trị thô) được cung cấp cho từng trường hợp liệt kê, thì giá trị đó có thể là một chuỗi, một ký tự hoặc một giá trị thuộc bất kỳ kiểu số nguyên hoặc dấu phẩy động nào Ngoài ra, các trường hợp liệt kê có thể chỉ định các giá trị liên quan thuộc bất kỳ loại nào sẽ được lưu trữ cùng với từng giá trị trường hợp khác nhau, giống như các liên kết hoặc biến thể thực hiện trong các ngôn ngữ khác. Bạn có thể xác định một tập hợp phổ biến các trường hợp có liên quan như một phần của một phép liệt kê, mỗi trường hợp có một tập hợp giá trị khác nhau của các loại phù hợp được liên kết với nó Bảng liệt kê trong Swift là loại hạng nhất theo cách riêng của chúng. Chúng áp dụng nhiều tính năng theo truyền thống chỉ được hỗ trợ bởi các lớp, chẳng hạn như các thuộc tính được tính toán để cung cấp thông tin bổ sung về giá trị hiện tại của phép liệt kê và các phương thức thể hiện để cung cấp chức năng liên quan đến các giá trị mà phép liệt kê đại diện. Việc liệt kê cũng có thể xác định các trình khởi tạo để cung cấp giá trị trường hợp ban đầu; Để biết thêm về các khả năng này, hãy xem Thuộc tính , Phương thức, Initialization, Extensions, and Protocols. Cú pháp liệt kê¶Bạn giới thiệu kiểu liệt kê với từ khóa enum và đặt toàn bộ định nghĩa của chúng trong một cặp dấu ngoặc nhọn - enum SomeEnumeration {
- // định nghĩa liệt kê ở đây
- }
Đây là một ví dụ cho bốn điểm chính của la bàn - enum Compasspoint {
- trường hợp bắc
- trường hợp nam
- trường hợp đông
- trường hợp tây
- }
Các giá trị được xác định trong một phép liệt kê (chẳng hạn như north , south , east và west ) là các trường hợp liệt kê của nó. Bạn sử dụng từ khóa case để giới thiệu các trường hợp liệt kê mới Ghi chú Các trường hợp liệt kê Swift không có giá trị số nguyên được đặt theo mặc định, không giống như các ngôn ngữ như C và Objective-C. Trong ví dụ về CompassPoint ở trên, north , south , east và west không hoàn toàn bằng với north 1, north 2, north 3 và north 4. Thay vào đó, các trường hợp liệt kê khác nhau là các giá trị theo đúng nghĩa của chúng, với một loại được xác định rõ ràng là CompassPoint Nhiều trường hợp có thể xuất hiện trên một dòng, được phân tách bằng dấu phẩy - enum Hành tinh {
- trường hợp thủy ngân , sao kim , earth, mars, jupiter, saturn, uranus, neptune
- }
Mỗi định nghĩa liệt kê xác định một loại mới. Giống như các loại khác trong Swift, tên của chúng (chẳng hạn như CompassPoint và north 7) bắt đầu bằng một chữ in hoa. Đặt tên cho các kiểu liệt kê là số ít thay vì số nhiều để chúng đọc là hiển nhiên - var directionToHead = CompassPoint . tây
Loại north 8 được suy ra khi nó được khởi tạo với một trong các giá trị có thể có của CompassPoint . Khi north 8 được khai báo là CompassPoint , bạn có thể đặt nó thành một giá trị CompassPoint khác bằng cách sử dụng cú pháp dấu chấm ngắn hơn - directionToHead =. đông
Loại north 8 đã được biết và vì vậy bạn có thể loại bỏ loại khi đặt giá trị của nó. Điều này làm cho mã dễ đọc hơn khi làm việc với các giá trị liệt kê được nhập rõ ràng Kết hợp các giá trị liệt kê với câu lệnh chuyển đổi¶Bạn có thể khớp các giá trị liệt kê riêng lẻ với câu lệnh south 4 - directionToHead =. nam
- chuyển directionToHead {
- trường hợp . bắc .
- print ( "Rất nhiều hành tinh có hướng bắc" )
- trường hợp . nam .
- print ( "Coi chừng chim cánh cụt" )
- trường hợp . phía đông .
- print ( "Nơi mặt trời mọc" )
- trường hợp . tây .
- print ( "Nơi bầu trời xanh" )
- }
- // In ra "Coi chừng chim cánh cụt"
Bạn có thể đọc mã này như “Hãy xem xét giá trị của north 8. Trong trường hợp nó bằng south 6, in ra south 7. Trong trường hợp nó bằng south 8, in ra south 9. ” …và như thế Như được mô tả trong Luồng điều khiển , một câu lệnh south 4 phải đầy đủ khi xem xét các trường hợp của bảng liệt kê. Nếu case cho east 2 bị bỏ qua, mã này không được biên dịch vì nó không xem xét danh sách đầy đủ của các trường hợp CompassPoint . Yêu cầu tính toàn diện đảm bảo rằng các trường hợp liệt kê không vô tình bị bỏ qua. Khi không thích hợp để cung cấp một case cho mọi trường hợp liệt kê, bạn có thể cung cấp một trường hợp east 5 để bao gồm bất kỳ trường hợp nào không được giải quyết rõ ràng - let somePlanet = Hành tinh . trái đất
- chuyển somePlanet {
- trường hợp . trái đất .
- in ( "Hầu như vô hại" )
- mặc định .
- print ( "Không phải là nơi an toàn cho con người" )
- }
- // In ra "Hầu như vô hại"
Lặp lại các trường hợp liệt kê¶Đối với một số kiểu liệt kê, sẽ rất hữu ích khi có một tập hợp tất cả các trường hợp của kiểu liệt kê đó. Bạn kích hoạt tính năng này bằng cách viết east 6 sau tên của bảng liệt kê. Swift hiển thị một tập hợp tất cả các trường hợp dưới dạng thuộc tính east 7 của kiểu liệt kê. Đây là một ví dụ - enum Đồ uống . CaseIterable {
- hộp cà phê , trà , juice
- }
- let numberOfChoices = Đồ uống . tất cả các trường hợp . đếm
- in ( " \ (numberOfChoices) beverages available")
- // In ra "3 loại đồ uống có sẵn"
Trong ví dụ trên, bạn viết east 8 để truy cập một bộ sưu tập chứa tất cả các trường hợp của phép liệt kê east 9. Bạn có thể sử dụng east 7 giống như bất kỳ bộ sưu tập nào khác—các phần tử của bộ sưu tập là các thể hiện của kiểu liệt kê, vì vậy trong trường hợp này, chúng là các giá trị east 9. Ví dụ trên đếm xem có bao nhiêu trường hợp và ví dụ bên dưới sử dụng vòng lặp west 2-west 3 để lặp qua tất cả các trường hợp - cho đồ uống trong Đồ uống . tất cả các trường hợp {
- in ( đồ uống )
- }
- // cà phê
- // trà
- // Nước ép
Cú pháp được sử dụng trong các ví dụ trên đánh dấu phép liệt kê là tuân theo giao thức west 4. Để biết thông tin về các giao thức, hãy xem Giao thức . Giá trị liên kết¶Các ví dụ trong phần trước cho thấy cách các trường hợp liệt kê là một giá trị được xác định (và nhập) theo đúng nghĩa của chúng. Bạn có thể đặt hằng số hoặc biến thành west 5 và kiểm tra giá trị này sau. Tuy nhiên, đôi khi rất hữu ích khi có thể lưu trữ các giá trị của các loại khác cùng với các giá trị trường hợp này. Thông tin bổ sung này được gọi là giá trị liên kết và nó thay đổi mỗi khi bạn sử dụng trường hợp đó làm giá trị trong mã của mình Bạn có thể xác định kiểu liệt kê Swift để lưu trữ các giá trị được liên kết của bất kỳ loại cụ thể nào và các loại giá trị có thể khác nhau đối với từng trường hợp liệt kê nếu cần. Các phép liệt kê tương tự như thế này được gọi là các hiệp hội phân biệt đối xử, các hiệp hội được gắn thẻ hoặc các biến thể trong các ngôn ngữ lập trình khác Ví dụ: giả sử hệ thống theo dõi hàng tồn kho cần theo dõi sản phẩm theo hai loại mã vạch khác nhau. Một số sản phẩm được dán nhãn mã vạch 1D ở định dạng UPC, sử dụng các số từ north 1 đến west 7. Mỗi mã vạch có một chữ số hệ thống số, theo sau là năm chữ số mã nhà sản xuất và năm chữ số mã sản phẩm. Theo sau chúng là một chữ số kiểm tra để xác minh rằng mã đã được quét chính xác Các sản phẩm khác được dán nhãn bằng mã vạch 2D ở định dạng mã QR, có thể sử dụng bất kỳ ký tự ISO 8859-1 nào và có thể mã hóa chuỗi dài tối đa 2.953 ký tự Thật thuận tiện cho hệ thống theo dõi hàng tồn kho để lưu trữ mã vạch UPC dưới dạng một bộ gồm bốn số nguyên và mã vạch mã QR dưới dạng một chuỗi có độ dài bất kỳ Trong Swift, một bảng liệt kê để xác định mã vạch sản phẩm thuộc một trong hai loại có thể trông như thế này - enum Mã vạch {
- trường hợp upc ( Int , Int, Int, Int)
- trường hợp qrCode ( Chuỗi )
- }
Điều này có thể được đọc như “Xác định một kiểu liệt kê có tên là west 8, có thể lấy giá trị của west 9 với giá trị được liên kết của loại (case 0, case 0, case 0, case 0) hoặc giá trị của case 4 với giá trị được liên kết của loại case 5. ” Định nghĩa này không cung cấp bất kỳ giá trị thực tế nào của case 0 hoặc case 5—nó chỉ xác định loại giá trị được liên kết mà hằng và biến west 8 có thể lưu trữ khi chúng bằng với case 9 hoặc CompassPoint 0 Sau đó, bạn có thể tạo mã vạch mới bằng một trong hai loại - var productBarcode = Barcode . upc ( 8 , 85909, 51226, 3)
Ví dụ này tạo một biến mới có tên là CompassPoint 1 và gán cho nó một giá trị là case 9 với một giá trị bộ dữ liệu được liên kết là CompassPoint 3 Bạn có thể gán cho cùng một sản phẩm một loại mã vạch khác - mã vạch sản phẩm =. qrCode ( "ABCDEFGHIJKLMNOP" )
Tại thời điểm này, case 9 ban đầu và các giá trị số nguyên của nó được thay thế bằng CompassPoint 0 mới và giá trị chuỗi của nó. Các hằng số và biến loại west 8 có thể lưu trữ một CompassPoint 7 hoặc một CompassPoint 8 (cùng với các giá trị được liên kết của chúng), nhưng chúng chỉ có thể lưu trữ một trong số chúng tại bất kỳ thời điểm nào Bạn có thể kiểm tra các loại mã vạch khác nhau bằng cách sử dụng câu lệnh chuyển đổi, tương tự như ví dụ trong Kết hợp giá trị liệt kê với câu lệnh chuyển đổi . Tuy nhiên, lần này, các giá trị liên quan được trích xuất như một phần của câu lệnh chuyển đổi. Bạn trích xuất từng giá trị được liên kết dưới dạng một hằng số (với tiền tố CompassPoint 9) hoặc một biến (với tiền tố north 0) để sử dụng trong phần thân của trường hợp south 4. - chuyển đổi mã vạch sản phẩm {
- trường hợp . upc ( let numberSystem , . let manufacturer, let product, let check):
- in ( "UPC. \ (hệ thống số), . "\(manufacturer), \(product), \(check)." )
- trường hợp . qrCode ( cho phép Mã sản phẩm ).
- in ( "Mã QR. \ (Mã sản phẩm). " )
- }
- // In "mã QR. ABCDEFGHIJKLMNOP. "
Nếu tất cả các giá trị được liên kết cho một trường hợp liệt kê được trích xuất dưới dạng hằng số hoặc nếu tất cả được trích xuất dưới dạng biến, bạn có thể đặt một chú thích north 0 hoặc CompassPoint 9 trước tên trường hợp để cho ngắn gọn - chuyển đổi mã vạch sản phẩm {
- trường hợp hãy . upc ( sốHệ thống , nhà sản xuất . , product, check):
- in ( "UPC. \ (hệ thống số), . "\(manufacturer), \(product), \(check)." )
- trường hợp hãy . qrCode ( Mã sản phẩm ).
- in ( "Mã QR. \ (Mã sản phẩm). " )
- }
- // In "mã QR. ABCDEFGHIJKLMNOP. "
Giá trị thô¶Ví dụ về mã vạch trong Giá trị được liên kết cho biết cách các trường hợp liệt kê có thể tuyên bố rằng chúng lưu trữ các giá trị được liên kết thuộc các loại khác nhau. Để thay thế cho các giá trị được liên kết, các trường hợp liệt kê có thể được điền sẵn các giá trị mặc định (được gọi là giá trị thô), tất cả đều thuộc cùng một loại. Đây là một ví dụ lưu trữ các giá trị ASCII thô cùng với các trường hợp liệt kê được đặt tên - enum ASCIIControl Character . Nhân vật {
- trường hợp tab = "\t"
- case lineFeed = "\n"
- case carriageReturn = "\r"
- }
Ở đây, các giá trị thô cho một phép liệt kê có tên là north 4 được định nghĩa là thuộc loại north 5 và được đặt thành một số ký tự điều khiển ASCII phổ biến hơn. Các giá trị của north 5 được mô tả trong Chuỗi và Ký tự . Giá trị thô có thể là chuỗi, ký tự hoặc bất kỳ loại số nguyên hoặc số dấu phẩy động nào. Mỗi giá trị thô phải là duy nhất trong khai báo liệt kê của nó Ghi chú Giá trị thô không giống với giá trị được liên kết. Các giá trị thô được đặt thành các giá trị được điền trước khi bạn xác định phép liệt kê trong mã của mình lần đầu tiên, chẳng hạn như ba mã ASCII ở trên. Giá trị thô cho một trường hợp liệt kê cụ thể luôn giống nhau. Các giá trị được liên kết được đặt khi bạn tạo một hằng số hoặc biến mới dựa trên một trong các trường hợp của phép liệt kê và có thể khác nhau mỗi khi bạn làm như vậy Giá trị thô được gán ngầm¶Khi bạn đang làm việc với các kiểu liệt kê lưu trữ các giá trị nguyên dạng chuỗi hoặc số nguyên, bạn không cần phải chỉ định một cách rõ ràng giá trị nguyên cho từng trường hợp. Khi bạn không làm như vậy, Swift sẽ tự động gán các giá trị cho bạn Ví dụ: khi số nguyên được sử dụng cho giá trị thô, giá trị ẩn cho mỗi trường hợp nhiều hơn trường hợp trước một. Nếu trường hợp đầu tiên không có giá trị được đặt, giá trị của nó là north 1 Phép liệt kê bên dưới là sự sàng lọc của phép liệt kê north 7 trước đó, với các giá trị nguyên nguyên để biểu thị thứ tự của mỗi hành tinh tính từ mặt trời - enum Hành tinh . Int {
- trường hợp thủy ngân = 1 , venus, earth, mars, jupiter, saturn, uranus, neptune
- }
Trong ví dụ trên, north 9 có giá trị thô rõ ràng là north 2, south 1 có giá trị thô tiềm ẩn là north 3, v.v. Khi các chuỗi được sử dụng cho các giá trị thô, giá trị ẩn cho từng trường hợp là văn bản tên của trường hợp đó Phép liệt kê bên dưới là sự sàng lọc của phép liệt kê CompassPoint trước đó, với các giá trị thô của chuỗi để biểu thị tên của từng hướng - enum Compasspoint . Chuỗi {
- trường hợp bắc , nam , east, west
- }
Trong ví dụ trên, south 4 có giá trị thô tiềm ẩn là south 5, v.v. Bạn truy cập giá trị thô của trường hợp liệt kê với thuộc tính south 6 của nó - let Trật tự trái đất = Hành tinh . trái đất . rawValue
- // EarthsOrder là 3
- let Hướng hoàng hôn = La bàn . tây . rawValue
- // hướng hoàng hôn là "tây"
Khởi tạo từ Giá trị thô¶Nếu bạn xác định một phép liệt kê với loại giá trị thô, thì phép liệt kê sẽ tự động nhận một trình khởi tạo lấy giá trị của loại giá trị thô (dưới dạng tham số có tên là south 6) và trả về trường hợp liệt kê hoặc south 8. Bạn có thể sử dụng trình khởi tạo này để thử tạo một thể hiện mới của phép liệt kê Ví dụ này xác định Sao Thiên Vương từ giá trị thô của nó là south 9 - let possiblePlanet = Hành tinh ( rawValue: 7 )
- // có thểPlanet thuộc loại Planet? . Sao Thiên Vương
Tuy nhiên, không phải tất cả các giá trị case 0 có thể sẽ tìm thấy một hành tinh phù hợp. Do đó, trình khởi tạo giá trị thô luôn trả về một trường hợp liệt kê tùy chọn. Trong ví dụ trên, east 1 thuộc loại east 2 hoặc “tùy chọn north 7. ” Ghi chú Trình khởi tạo giá trị thô là trình khởi tạo có thể gặp lỗi, bởi vì không phải mọi giá trị thô sẽ trả về trường hợp liệt kê. Để biết thêm thông tin, hãy xem Trình khởi chạy không thành công . Nếu bạn cố gắng tìm một hành tinh có vị trí là east 4, thì giá trị tùy chọn north 7 được trả về bởi bộ khởi tạo giá trị thô sẽ là south 8 - let positionToFind = 11
- if let somePlanet = Hành tinh(rawValue: positionToFind ) {
- chuyển somePlanet {
- trường hợp . trái đất .
- in ( "Hầu như vô hại" )
- mặc định .
- print ( "Không phải là nơi an toàn cho con người" )
- }
- } khác {
- print ( "Không có hành tinh nào ở vị trí \ (positionToFind)")
- }
- // In ra "Không có hành tinh nào ở vị trí 11"
Ví dụ này sử dụng liên kết tùy chọn để thử truy cập một hành tinh có giá trị thô là east 4. Câu lệnh east 8 tạo một north 7 tùy chọn và đặt north 00 thành giá trị của north 7 tùy chọn đó nếu nó có thể được truy xuất. Trong trường hợp này, không thể truy xuất một hành tinh có vị trí là east 4 và do đó, nhánh north 03 được thực thi thay thế Phép liệt kê đệ quy¶Phép liệt kê đệ quy là phép liệt kê có một thể hiện khác của phép liệt kê làm giá trị liên quan cho một hoặc nhiều trường hợp liệt kê. Bạn chỉ ra rằng trường hợp liệt kê là đệ quy bằng cách viết north 04 trước nó, điều này báo cho trình biên dịch chèn lớp điều hướng cần thiết Ví dụ, đây là một kiểu liệt kê lưu trữ các biểu thức số học đơn giản - enum Biểu thức số học {
- trường hợp số ( Int )
- gián tiếp trường hợp phép cộng ( Biểu thức số học, ArithmeticExpression)
- gián tiếp trường hợp phép nhân ( Biểu thức số học, ArithmeticExpression)
- }
Bạn cũng có thể viết north 04 trước khi bắt đầu phép liệt kê để bật tính năng gián tiếp cho tất cả các trường hợp của phép liệt kê có giá trị liên quan - gián tiếp enum Biểu thức số học {
- trường hợp số ( Int )
- trường hợp phép cộng ( Biểu thức số học , ArithmeticExpression)
- trường hợp phép nhân ( Biểu thức số học , ArithmeticExpression)
- }
Kiểu liệt kê này có thể lưu trữ ba loại biểu thức số học. một số đơn giản, phép cộng hai biểu thức và phép nhân hai biểu thức. Các trường hợp north 06 và north 07 có các giá trị được liên kết cũng là các biểu thức số học—các giá trị được liên kết này giúp có thể lồng các biểu thức. Ví dụ, biểu thức north 08 có một số ở bên phải của phép nhân và một biểu thức khác ở bên trái của phép nhân. Vì dữ liệu được lồng vào nhau nên phép liệt kê được sử dụng để lưu trữ dữ liệu cũng cần hỗ trợ lồng nhau—điều này có nghĩa là phép liệt kê cần phải được đệ quy. Mã bên dưới hiển thị phép liệt kê đệ quy north 09 được tạo cho north 08 - hãy năm = Biểu thức số học . số ( 5 )
- hãy bốn = Biểu thức số học . số ( 4 )
- hãy tổng = Biểu thức số học . bổ sung ( năm , bốn)
- let product = Biểu thức số học . phép nhân ( tổng , Biểu thức số học . .số ( 2 ))
Hàm đệ quy là một cách đơn giản để làm việc với dữ liệu có cấu trúc đệ quy. Ví dụ: đây là một hàm đánh giá một biểu thức số học - hàm đánh giá ( _ biểu thức: Biểu thức số học ) -> Int {
- chuyển biểu thức {
- trường hợp hãy . số ( giá trị ).
- trả về giá trị
- trường hợp hãy . bổ sung ( trái , phải . ):
- return đánh giá ( left ) + evaluate(right)
- trường hợp hãy . phép nhân ( trái , phải . ):
- return đánh giá ( left ) * evaluate(right)
- }
- }
- in ( đánh giá ( sản phẩm))
- // In ra "18"
Hàm này đánh giá một số đơn giản bằng cách trả về giá trị được liên kết. Nó đánh giá một phép cộng hoặc phép nhân bằng cách đánh giá biểu thức ở vế trái, đánh giá biểu thức ở vế phải, rồi cộng hoặc nhân chúng |