Swift - Hướng dẫn nhanh
Swift 4 là một ngôn ngữ lập trình mới do Apple Inc phát triển để phát triển iOS và OS X. Swift 4 sử dụng những gì tốt nhất của C và Objective-C, không có ràng buộc về khả năng tương thích của C.
Swift 4 sử dụng các mẫu lập trình an toàn.
Swift 4 cung cấp các tính năng lập trình hiện đại.
Swift 4 cung cấp cú pháp giống Objective-C.
Swift 4 là một cách tuyệt vời để viết các ứng dụng iOS và OS X.
Swift 4 cung cấp khả năng truy cập liền mạch vào các khuôn khổ Cocoa hiện có.
Swift 4 hợp nhất các phần thủ tục và hướng đối tượng của ngôn ngữ.
Swift 4 không cần nhập thư viện riêng để hỗ trợ các chức năng như đầu vào / đầu ra hoặc xử lý chuỗi.
Swift 4 sử dụng cùng thời gian chạy với hệ thống obj-C hiện có trên Mac OS và iOS, cho phép các chương trình Swift 4 chạy trên nhiều nền tảng iOS 6 và OS X 10.8 hiện có.
Swift 4 đi kèm với tính năng sân chơi, nơi các lập trình viên Swift 4 có thể viết mã của họ và thực thi nó để xem kết quả ngay lập tức.
Bản phát hành công khai đầu tiên của Swift được phát hành vào năm 2010. Phải mất Chris Lattnergần 14 năm để đưa ra phiên bản chính thức đầu tiên và sau đó, nó đã được hỗ trợ bởi nhiều cộng tác viên khác. Swift 4 đã được đưa vào Xcode 6 beta.
Các nhà thiết kế Swift lấy ý tưởng từ nhiều ngôn ngữ phổ biến khác như Objective-C, Rust, Haskell, Ruby, Python, C # và CLU.
Thiết lập môi trường cục bộ
Swift 4 cung cấp nền tảng Playground cho mục đích học tập và chúng tôi sẽ thiết lập tương tự. Bạn cần phần mềm xCode để bắt đầu viết mã Swift 4 trong Playground. Khi bạn đã hiểu rõ về các khái niệm của Swift 4, bạn có thể sử dụng xCode IDE để phát triển ứng dụng iOS / OS x.
Để bắt đầu, chúng tôi coi bạn đã có tài khoản tại trang web Nhà phát triển Apple. Sau khi bạn đã đăng nhập, hãy truy cập liên kết sau - Tải xuống cho Nhà phát triển Apple
Điều này sẽ liệt kê một số phần mềm có sẵn như sau:
Bây giờ chọn xCode và tải xuống bằng cách nhấp vào liên kết nhất định gần hình ảnh đĩa. Sau khi tải xuống tệp dmg, bạn có thể cài đặt nó bằng cách chỉ cần nhấp đúp vào nó và làm theo hướng dẫn đã cho. Cuối cùng, làm theo các hướng dẫn đã cho và thả biểu tượng xCode vào thư mục Ứng dụng.
Bây giờ bạn đã cài đặt xCode trên máy của mình. Tiếp theo, mở Xcode từ thư mục Ứng dụng và tiếp tục sau khi chấp nhận các điều khoản và điều kiện. Nếu mọi thứ đều ổn, bạn sẽ nhận được màn hình sau:
Lựa chọn Get started with a playgroundvà nhập tên cho sân chơi và chọn iOS làm nền tảng. Cuối cùng, bạn sẽ nhận được cửa sổ Playground như sau:
Sau đây là mã lấy từ Cửa sổ sân chơi Swift 4 mặc định.
import UIKit
var str = "Hello, playground"
Nếu bạn tạo cùng một chương trình cho chương trình OS X, thì chương trình đó sẽ bao gồm nhập Cacao và chương trình sẽ giống như sau:
import Cocoa
var str = "Hello, playground"
Khi chương trình trên được tải, nó sẽ hiển thị kết quả sau trong vùng kết quả Playground (Bên tay phải).
Hello, playground
Xin chúc mừng, bạn đã sẵn sàng môi trường lập trình Swift 4 và bạn có thể tiếp tục với phương tiện học tập của mình "Tutorials Point".
Chúng ta đã thấy một đoạn chương trình Swift 4 trong khi thiết lập môi trường. Hãy bắt đầu lại một lần nữa với những điều sauHello, World! chương trình được tạo cho sân chơi OS X, bao gồm import Cocoa như hình dưới đây -
/* My first program in Swift 4 */
var myString = "Hello, World!"
print(myString)
Nếu bạn tạo cùng một chương trình cho sân chơi iOS, thì nó sẽ bao gồm import UIKit và chương trình sẽ như sau:
import UIKit
var myString = "Hello, World!"
print(myString)
Khi chúng tôi chạy chương trình trên bằng một sân chơi thích hợp, chúng tôi sẽ nhận được kết quả sau:
Hello, World!
Bây giờ chúng ta hãy xem cấu trúc cơ bản của một chương trình Swift 4, để bạn có thể dễ dàng hiểu được các khối xây dựng cơ bản của ngôn ngữ lập trình Swift 4.
Nhập trong Swift 4
Bạn có thể dùng importđể nhập bất kỳ khung Objective-C (hoặc thư viện C) nào trực tiếp vào chương trình Swift 4 của bạn. Ví dụ, trênimport cocoa câu lệnh làm cho tất cả thư viện Cocoa, API và thời gian chạy tạo thành lớp phát triển cho tất cả OS X, có sẵn trong Swift 4.
Cocoa được triển khai trong Objective-C, là một tập hợp siêu tốc của C, vì vậy có thể dễ dàng trộn C và thậm chí cả C ++ vào các ứng dụng Swift 4 của bạn.
Mã thông báo trong Swift 4
Một chương trình Swift 4 bao gồm các mã thông báo khác nhau và mã thông báo là một từ khóa, một mã định danh, một hằng số, một chuỗi ký tự hoặc một ký hiệu. Ví dụ: câu lệnh Swift 4 sau đây bao gồm ba mã thông báo:
print("test!")
The individual tokens are:
print("test!")
Bình luận
Nhận xét giống như văn bản trợ giúp trong chương trình Swift 4 của bạn. Chúng được trình biên dịch bỏ qua. Nhận xét nhiều dòng bắt đầu bằng / * và kết thúc bằng các ký tự * / như hình dưới đây -
/* My first program in Swift 4 */
Nhận xét nhiều dòng có thể được lồng trong Swift 4. Sau đây là nhận xét hợp lệ trong Swift 4:
/* My first program in Swift 4 is Hello, World!
/* Where as second program is Hello, Swift 4! */ */
Nhận xét một dòng được viết bằng cách sử dụng // ở đầu nhận xét.
// My first program in Swift 4
Dấu chấm phẩy
Swift 4 không yêu cầu bạn nhập dấu chấm phẩy (;) sau mỗi câu lệnh trong mã của bạn, mặc dù nó là tùy chọn; và nếu bạn sử dụng dấu chấm phẩy, thì trình biên dịch sẽ không phàn nàn về điều đó.
Tuy nhiên, nếu bạn đang sử dụng nhiều câu lệnh trong cùng một dòng, thì bắt buộc phải sử dụng dấu chấm phẩy làm dấu phân cách, nếu không trình biên dịch sẽ phát sinh lỗi cú pháp. Bạn có thể viết Hello, World ở trên! chương trình như sau -
/* My first program in Swift 4 */
var myString = "Hello, World!"; print(myString)
Định danh
Định danh Swift 4 là tên được sử dụng để xác định một biến, hàm hoặc bất kỳ mục nào khác do người dùng xác định. Mã định danh bắt đầu bằng bảng chữ cái từ A đến Z hoặc từ a đến z hoặc dấu gạch dưới _ theo sau là không hoặc nhiều chữ cái, dấu gạch dưới và chữ số (0 đến 9).
Swift 4 không cho phép các ký tự đặc biệt như @, $ và% trong số nhận dạng. Swift 4 là mộtcase sensitivengôn ngữ lập trình. Do đó, Manpower và nhân lực là hai định danh khác nhau trong Swift 4. Dưới đây là một số ví dụ về các định danh được chấp nhận -
Azad zara abc move_name a_123
myname50 _temp j a23b9 retVal
Để sử dụng một từ dành riêng làm định danh, bạn sẽ cần đặt dấu gạch ngược (`) trước và sau nó. Ví dụ,class không phải là một định danh hợp lệ, nhưng `class`là hợp lệ.
Từ khóa
Các từ khóa sau được dành riêng trong Swift 4. Những từ dành riêng này không được dùng làm hằng số hoặc biến hoặc bất kỳ tên định danh nào khác, trừ khi chúng được thoát bằng dấu gạch ngược -
Từ khóa được sử dụng trong khai báo
Lớp học | deinit | Enum | sự mở rộng |
Chức năng | nhập khẩu | Trong đó | nội bộ |
Để cho | nhà điều hành | riêng tư | giao thức |
công cộng | tĩnh | cấu trúc | chỉ số dưới |
kiểu chữ | var |
Các từ khóa được sử dụng trong các câu lệnh
phá vỡ | trường hợp | tiếp tục | mặc định |
làm | khác | thất bại | cho |
nếu | trong | trở về | công tắc điện |
Ở đâu | trong khi |
Các từ khóa được sử dụng trong các biểu thức và loại
như | dynamicType | sai | Là |
không | bản thân | Bản thân | siêu |
thật | _CỘT_ | _TẬP TIN_ | _CHỨC NĂNG_ |
_HÀNG_ |
Từ khóa được sử dụng trong các ngữ cảnh cụ thể
sự liên kết | tiện | năng động | didSet |
sau cùng | được | infix | inout |
lười biếng | trái | đột biến | không ai |
không nói | không bắt buộc | ghi đè | hậu tố |
quyền ưu tiên | tiếp đầu ngữ | Giao thức | cần thiết |
đúng | bộ | Kiểu | không biết |
Yếu | willSet |
Khoảng trắng
Một dòng chỉ chứa khoảng trắng, có thể kèm theo chú thích, được gọi là dòng trống và trình biên dịch Swift 4 hoàn toàn bỏ qua nó.
Khoảng trắng là thuật ngữ được sử dụng trong Swift 4 để mô tả khoảng trống, tab, ký tự dòng mới và nhận xét. Khoảng trắng phân tách một phần của câu lệnh với phần khác và cho phép trình biên dịch xác định vị trí một phần tử trong câu lệnh, chẳng hạn như int, kết thúc và phần tử tiếp theo bắt đầu. Do đó, trong câu lệnh sau:
var age
Phải có ít nhất một ký tự khoảng trắng (thường là khoảng trắng) giữa var và ageđể trình biên dịch có thể phân biệt chúng. Mặt khác, trong câu lệnh sau:
int fruit = apples + oranges //get the total fruits
Không cần ký tự khoảng trắng nào giữa trái cây và =, hoặc giữa = và táo, mặc dù bạn có thể thêm một số ký tự để dễ đọc hơn.
Không gian ở cả hai phía của một toán tử phải bằng nhau, ví dụ.
int fruit = apples +oranges //is a wrong statement
int fruit = apples + oranges //is a Correct statement
Chữ viết
Một chữ là mã nguồn biểu diễn giá trị của một số nguyên, số dấu phẩy động hoặc kiểu chuỗi. Sau đây là các ví dụ về các chữ -
92 // Integer literal
4.24159 // Floating-point literal
"Hello, World!" // String literal
In bằng Swift
Để in nhanh bất cứ thứ gì, chúng ta có từ khóa 'print'.
In có ba thuộc tính khác nhau.
Items - Các mục sẽ được in
Separator - dấu phân cách giữa các mục
Terminator - giá trị mà dòng sẽ kết thúc, hãy xem một ví dụ và cú pháp tương tự.
print("Items to print", separator: "Value " , terminator: "Value")
// E.g. of print statement.
print("Value one")
// prints "Value one \n" Adds, \n as terminator and " " as separator by
default.
print("Value one","Value two", separator: " Next Value" , terminator: " End")
//prints "Value one Next Value Value two End"
Trong đoạn mã trên, câu lệnh in đầu tiên thêm \ n, newline Feed làm dấu chấm dứt theo mặc định, trong đó như trong câu lệnh in thứ hai, chúng tôi đã cho "End" làm dấu chấm dứt, do đó nó sẽ in "End" thay vì \ n.
Chúng tôi có thể cung cấp bộ phân tách và đầu cuối tùy chỉnh của chúng tôi theo yêu cầu của chúng tôi.
Trong khi lập trình bằng bất kỳ ngôn ngữ lập trình nào, bạn cần sử dụng các loại biến khác nhau để lưu trữ thông tin. Các biến không là gì ngoài các vị trí bộ nhớ dành riêng để lưu trữ các giá trị. Điều này có nghĩa là khi bạn tạo một biến, bạn dự trữ một số không gian trong bộ nhớ.
Bạn có thể muốn lưu trữ thông tin của nhiều kiểu dữ liệu khác nhau như chuỗi, ký tự, ký tự rộng, số nguyên, dấu phẩy động, Boolean, v.v. Dựa trên kiểu dữ liệu của một biến, hệ điều hành phân bổ bộ nhớ và quyết định những gì có thể được lưu trữ trong ký ức.
Các loại dữ liệu tích hợp
Swift 4 cung cấp cho lập trình viên rất nhiều loại dữ liệu tích hợp cũng như kiểu dữ liệu do người dùng xác định. Các loại kiểu dữ liệu cơ bản sau đây thường gặp nhất khi khai báo biến:
Int or UInt- Điều này được sử dụng cho các số nguyên. Cụ thể hơn, bạn có thể sử dụng Int32, Int64 để xác định số nguyên có dấu 32 hoặc 64 bit, trong khi UInt32 hoặc UInt64 để xác định các biến số nguyên không dấu 32 hoặc 64 bit. Ví dụ, 42 và -23.
Float- Điều này được sử dụng để biểu diễn một số dấu phẩy động 32 bit và các số có dấu thập phân nhỏ hơn. Ví dụ: 3,14159, 0,1 và -273,188.
Double- Điều này được sử dụng để biểu diễn một số dấu phẩy động 64 bit và được sử dụng khi các giá trị dấu phẩy động phải rất lớn. Ví dụ: 3,14159, 0,1 và -273,188.
Bool - Giá trị này đại diện cho một giá trị Boolean là true hoặc false.
String- Đây là một bộ sưu tập các ký tự có thứ tự. Ví dụ: "Xin chào, Thế giới!"
Character- Đây là một chuỗi ký tự đơn theo nghĩa đen. Ví dụ: "C"
Optional - Điều này đại diện cho một biến có thể giữ giá trị hoặc không có giá trị.
Tuples - Điều này được sử dụng để nhóm nhiều giá trị trong một Giá trị tổng hợp.
Chúng tôi đã liệt kê ở đây một vài điểm quan trọng liên quan đến kiểu Số nguyên -
Trên nền tảng 32-bit, Int có cùng kích thước với Int32.
Trên nền tảng 64-bit, Int có cùng kích thước với Int64.
Trên nền tảng 32-bit, UInt có cùng kích thước với UInt32.
Trên nền tảng 64-bit, UInt có cùng kích thước với UInt64.
Int8, Int16, Int32, Int64 có thể được sử dụng để biểu thị các dạng 8 Bit, 16 Bit, 32 Bit và 64 Bit của số nguyên có dấu.
UInt8, UInt16, UInt32 và UInt64 có thể được sử dụng để biểu diễn các dạng 8 Bit, 16 Bit, 32 Bit và 64 Bit của số nguyên không dấu.
Giá trị ràng buộc
Bảng sau đây cho thấy loại biến, cần bao nhiêu bộ nhớ để lưu giá trị trong bộ nhớ và giá trị lớn nhất và nhỏ nhất có thể được lưu trong loại biến đó là bao nhiêu.
Kiểu | Chiều rộng bit điển hình | Phạm vi điển hình |
---|---|---|
Int8 | 1byte | -127 đến 127 |
UInt8 | 1byte | 0 đến 255 |
Int32 | 4byte | -2147483648 đến 2147483647 |
UInt32 | 4byte | 0 đến 4294967295 |
Int64 | 8byte | -9223372036854775808 đến 9223372036854775807 |
UInt64 | 8byte | 0 đến 18446744073709551615 |
Phao nổi | 4byte | 1.2E-38 đến 3.4E + 38 (~ 6 chữ số) |
Gấp đôi | 8byte | 2.3E-308 đến 1.7E + 308 (~ 15 chữ số) |
Nhập bí danh
Bạn có thể tạo tên mới cho một loại hiện có bằng cách sử dụng typealias. Đây là cú pháp đơn giản để xác định một kiểu mới bằng cách sử dụng typealias:
typealias newname = type
Ví dụ: dòng sau hướng dẫn trình biên dịch rằng Feet là một tên khác của Int -
typealias Feet = Int
Bây giờ, khai báo sau là hoàn toàn hợp pháp và tạo ra một biến số nguyên được gọi là khoảng cách -
typealias Feet = Int
var distance: Feet = 100
print(distance)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau.
100
Loại an toàn
Swift 4 là một ngôn ngữ an toàn về kiểu chữ, có nghĩa là nếu một phần mã của bạn yêu cầu một Chuỗi, bạn không thể chuyển nó thành Int do nhầm lẫn.
Vì Swift 4 là kiểu an toàn nên nó thực hiện kiểm tra kiểu khi biên dịch mã của bạn và gắn cờ bất kỳ kiểu không khớp nào là lỗi.
var varA = 42
varA = "This is hello"
print(varA)
Khi chúng tôi biên dịch chương trình trên, nó tạo ra lỗi thời gian biên dịch sau.
main.swift:2:8: error: cannot assign value of type 'String' to type 'Int'
varA = "This is hello"
Nhập suy luận
Suy luận kiểu cho phép trình biên dịch tự động suy ra kiểu của một biểu thức cụ thể khi nó biên dịch mã của bạn, chỉ đơn giản bằng cách kiểm tra các giá trị bạn cung cấp. Swift 4 sử dụng kiểu suy luận để tìm ra kiểu phù hợp như sau.
// varA is inferred to be of type Int
var varA = 42
print(varA)
// varB is inferred to be of type Double
var varB = 3.14159
print(varB)
// varC is also inferred to be of type Double
var varC = 3 + 0.14159
print(varC)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
42
3.14159
3.14159
Một biến cung cấp cho chúng ta bộ nhớ được đặt tên mà chương trình của chúng ta có thể thao tác. Mỗi biến trong Swift 4 có một kiểu cụ thể, xác định kích thước và cách bố trí bộ nhớ của biến; phạm vi giá trị có thể được lưu trữ trong bộ nhớ đó; và tập hợp các thao tác có thể áp dụng cho biến.
Swift 4 hỗ trợ các loại biến cơ bản sau:
Int or UInt- Điều này được sử dụng cho các số nguyên. Cụ thể hơn, bạn có thể sử dụng Int32, Int64 để xác định số nguyên có dấu 32 hoặc 64 bit, trong khi UInt32 hoặc UInt64 để xác định các biến số nguyên không dấu 32 hoặc 64 bit. Ví dụ, 42 và -23.
Float- Điều này được sử dụng để biểu diễn một số dấu phẩy động 32 bit. Nó được sử dụng để giữ các số có dấu thập phân nhỏ hơn. Ví dụ: 3,14159, 0,1 và -273,188.
Double- Điều này được sử dụng để biểu diễn một số dấu phẩy động 64 bit và được sử dụng khi các giá trị dấu phẩy động phải rất lớn. Ví dụ: 3,14159, 0,1 và -273.158.
Bool - Giá trị này đại diện cho một giá trị Boolean là true hoặc false.
String- Đây là một bộ sưu tập các ký tự có thứ tự. Ví dụ: "Xin chào, Thế giới!"
Character- Đây là một chuỗi ký tự đơn theo nghĩa đen. Ví dụ: "C"
Swift 4 cũng cho phép xác định nhiều loại biến khác nhau mà chúng ta sẽ trình bày trong các chương tiếp theo, chẳng hạn như Optional, Array, Dictionaries, Structures, và Classes.
Phần sau sẽ trình bày về cách khai báo và sử dụng các loại biến trong lập trình Swift 4.
Sự định nghĩa biến
Một khai báo biến cho trình biên dịch biết vị trí và dung lượng để tạo bộ lưu trữ cho biến. Trước khi sử dụng các biến, bạn phải khai báo chúng bằngvar từ khóa như sau -
var variableName = <initial value>
Ví dụ sau đây cho thấy cách khai báo một biến trong Swift 4:
var varA = 42
print(varA)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
42
Nhập chú thích
Bạn có thể cung cấp một type annotationkhi bạn khai báo một biến, hãy rõ ràng về loại giá trị mà biến có thể lưu trữ. Đây là cú pháp -
var variableName:<data type> = <optional initial value>
Ví dụ sau đây cho thấy cách khai báo một biến trong Swift 4 bằng Annotation. Ở đây, điều quan trọng cần lưu ý là nếu chúng ta không sử dụng chú thích kiểu, thì bắt buộc phải cung cấp giá trị ban đầu cho biến, nếu không chúng ta chỉ có thể khai báo biến của mình bằng cách sử dụng chú thích kiểu.
var varA = 42
print(varA)
var varB:Float
varB = 3.14159
print(varB)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
42
3.1415901184082
Đặt tên biến
Tên của một biến có thể bao gồm các chữ cái, chữ số và ký tự gạch dưới. Nó phải bắt đầu bằng một chữ cái hoặc một dấu gạch dưới. Chữ hoa và chữ thường khác nhau vì Swift 4 là ngôn ngữ lập trình phân biệt chữ hoa chữ thường.
Bạn có thể sử dụng các ký tự đơn giản hoặc Unicode để đặt tên cho các biến của mình. Các ví dụ sau đây cho thấy cách bạn có thể đặt tên cho các biến:
var _var = "Hello, Swift 4!"
print(_var)
var 你好 = "你好世界"
print(你好)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau.
Hello, Swift 4!
你好世界
In các biến
Bạn có thể in giá trị hiện tại của một hằng số hoặc biến bằng hàm in. Bạn có thể nội suy một giá trị biến bằng cách đặt tên trong dấu ngoặc đơn và thoát tên đó bằng dấu gạch chéo ngược trước dấu ngoặc mở: Sau đây là các ví dụ hợp lệ:
var varA = "Godzilla"
var varB = 1000.00
print("Value of \(varA) is more than \(varB) millions")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau.
Value of Godzilla is more than 1000.0 millions
Swift 4 cũng giới thiệu Optionalsloại, xử lý trường hợp không có giá trị. Các tùy chọn cho biết "có một giá trị và nó bằng x" hoặc "không có một giá trị nào cả".
Tùy chọn là một loại riêng của nó, thực sự là một trong những enums siêu cấp mới của Swift 4. Nó có hai giá trị có thể,None và Some(T), Ở đâu T là một giá trị liên quan của kiểu dữ liệu chính xác có sẵn trong Swift 4.
Đây là một khai báo Số nguyên tùy chọn -
var perhapsInt: Int?
Đây là một khai báo Chuỗi tùy chọn -
var perhapsStr: String?
Khai báo trên tương đương với việc khởi tạo nó thành nil có nghĩa là không có giá trị -
var perhapsStr: String? = nil
Hãy lấy ví dụ sau để hiểu cách hoạt động của các tùy chọn trong Swift 4:
var myString:String? = nil
if myString != nil {
print(myString)
} else {
print("myString has nil value")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
myString has nil value
Tùy chọn tương tự như sử dụng nil với các con trỏ trong Objective-C, nhưng chúng hoạt động với mọi kiểu, không chỉ các lớp.
Buộc mở gói
Nếu bạn đã xác định một biến là optional, sau đó để nhận giá trị từ biến này, bạn sẽ phải unwrapnó. Điều này chỉ có nghĩa là đặt một dấu chấm than ở cuối biến.
Hãy lấy một ví dụ đơn giản -
var myString:String?
myString = "Hello, Swift 4!"
if myString != nil {
print(myString)
} else {
print("myString has nil value")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Optional("Hello, Swift 4!")
Bây giờ chúng ta hãy áp dụng việc mở gói để nhận được giá trị chính xác của biến -
var myString:String?
myString = "Hello, Swift 4!"
if myString != nil {
print( myString! )
} else {
print("myString has nil value")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau.
Hello, Swift 4!
Tự động mở gói
Bạn có thể khai báo các biến tùy chọn bằng cách sử dụng dấu chấm than thay vì dấu chấm hỏi. Các biến tùy chọn như vậy sẽ tự động mở ra và bạn không cần sử dụng thêm bất kỳ dấu chấm than nào ở cuối biến để nhận giá trị được chỉ định. Hãy lấy một ví dụ đơn giản -
var myString:String!
myString = "Hello, Swift 4!"
if myString != nil {
print(myString)
} else {
print("myString has nil value")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Hello, Swift 4!
Ràng buộc tùy chọn
Sử dụng liên kết tùy chọn để tìm hiểu xem một tùy chọn có chứa một giá trị hay không và nếu có, để cung cấp giá trị đó dưới dạng một hằng số hoặc biến tạm thời.
Một ràng buộc tùy chọn cho if tuyên bố như sau:
if let constantName = someOptional {
statements
}
Hãy lấy một ví dụ đơn giản để hiểu cách sử dụng ràng buộc tùy chọn -
var myString:String?
myString = "Hello, Swift 4!"
if let yourString = myString {
print("Your string has - \(yourString)")
} else {
print("Your string does not have a value")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Your string has - Hello, Swift 4!
Swift 4 cũng giới thiệu Tuples loại, được sử dụng để nhóm nhiều giá trị trong một giá trị ghép đơn lẻ.
Các giá trị trong một bộ giá trị có thể thuộc bất kỳ loại nào và không cần phải cùng loại.
Ví dụ: ("Tutorials Point", 123) là một bộ giá trị có hai giá trị, một là Kiểu chuỗi và một là kiểu số nguyên. Đó là một mệnh lệnh hợp pháp.
let implementError = (501, "Not implement") là lỗi khi một cái gì đó trên máy chủ không được triển khai, Nó trả về hai giá trị. Mã lỗi và mô tả.
Bạn có thể tạo bộ giá trị từ nhiều giá trị tùy thích và từ bất kỳ số lượng kiểu dữ liệu khác nhau nào.
Đây là cú pháp của khai báo Tuple -
var TupleName = (Value1, value2,… any number of values)
Đây là một khai báo Tuple -
var error501 = (501, “Not implemented”)
Bạn có thể truy cập các giá trị của tuple bằng cách sử dụng các số chỉ mục bắt đầu từ 0.
Đây là một ví dụ về cách truy cập các giá trị tuple -
print(“The code is\(error501.0)”)
print(“The definition of error is\(error501.1)”)
Bạn có thể đặt tên cho các biến của một bộ trong khi khai báo và bạn có thể gọi chúng bằng tên của chúng
var error501 = (errorCode: 501, description: “Not Implemented”)
print(error501.errorCode) // prints 501.
Tuples hữu ích trong việc trả về nhiều giá trị từ một hàm. Giống như, một ứng dụng web có thể trả về nhiều loại ("String", Int) để hiển thị việc tải thành công hay thất bại.
Bằng cách trả về các giá trị khác nhau trong một tuple, chúng ta có thể đưa ra quyết định tùy thuộc vào các loại tuple khác nhau.
Note - Tuples hữu ích cho các giá trị tạm thời và không phù hợp với dữ liệu phức tạp.
Hằng số đề cập đến các giá trị cố định mà một chương trình không được thay đổi trong quá trình thực thi. Hằng số có thể thuộc bất kỳ kiểu dữ liệu cơ bản nào như hằng số nguyên, hằng số động, hằng ký tự hoặc chuỗi ký tự . Có cả các hằng số liệt kê .
Constants được xử lý giống như các biến thông thường ngoại trừ thực tế là các giá trị của chúng không thể được sửa đổi sau khi định nghĩa.
Khai báo hằng số
Trước khi bạn sử dụng hằng số, bạn phải khai báo chúng bằng let từ khóa như sau -
let constantName = <initial value>
Sau đây là một ví dụ đơn giản để chỉ ra cách khai báo một hằng số trong Swift 4:
let constA = 42
print(constA)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
42
Nhập chú thích
Bạn có thể cung cấp một type annotationkhi bạn khai báo một hằng số, hãy rõ ràng về loại giá trị mà hằng số có thể lưu trữ. Sau đây là cú pháp:
var constantName:<data type> = <optional initial value>
Ví dụ sau đây cho thấy cách khai báo một hằng số trong Swift 4 bằng Annotation. Ở đây, điều quan trọng cần lưu ý là bắt buộc phải cung cấp giá trị ban đầu trong khi tạo một hằng số -
let constA = 42
print(constA)
let constB:Float = 3.14159
print(constB)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau.
42
3.1415901184082
Hằng số đặt tên
Tên của một hằng số có thể bao gồm các chữ cái, chữ số và ký tự gạch dưới. Nó phải bắt đầu bằng một chữ cái hoặc một dấu gạch dưới. Chữ hoa và chữ thường khác nhau vì Swift 4 là ngôn ngữ lập trình phân biệt chữ hoa chữ thường.
Bạn có thể sử dụng các ký tự đơn giản hoặc Unicode để đặt tên cho các biến của mình. Sau đây là các ví dụ hợp lệ -
let _const = "Hello, Swift 4!"
print(_const)
let 你好 = "你好世界"
print(你好)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Hello, Swift 4!
你好世界
Các hằng số in
Bạn có thể in giá trị hiện tại của một hằng số hoặc biến bằng cách sử dụng printchức năng. Bạn có thể nội suy một giá trị biến bằng cách đặt tên trong dấu ngoặc đơn và thoát tên đó bằng dấu gạch chéo ngược trước dấu ngoặc mở: Sau đây là các ví dụ hợp lệ:
let constA = "Godzilla"
let constB = 1000.00
print("Value of \(constA) is more than \(constB) millions")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Value of Godzilla is more than 1000.0 millions
Một chữ là mã nguồn biểu diễn giá trị của một số nguyên, số dấu phẩy động hoặc kiểu chuỗi. Sau đây là các ví dụ về các chữ -
42 // Integer literal
3.14159 // Floating-point literal
"Hello, world!" // String literal
Chữ số nguyên
Một ký tự số nguyên có thể là một hằng số thập phân, nhị phân, bát phân hoặc thập lục phân. Các ký tự nhị phân bắt đầu bằng 0b, các ký tự bát phân bắt đầu bằng 0o và các ký tự thập lục phân bắt đầu bằng 0x và không có gì cho số thập phân.
Dưới đây là một số ví dụ về các ký tự số nguyên -
let decimalInteger = 17 // 17 in decimal notation
let binaryInteger = 0b10001 // 17 in binary notation
let octalInteger = 0o21 // 17 in octal notation
let hexadecimalInteger = 0x11 // 17 in hexadecimal notation
Chữ nổi dấu chấm động
Một ký tự dấu phẩy động có một phần nguyên, một dấu thập phân, một phần thập phân và một phần mũ. Bạn có thể biểu diễn các ký tự dấu phẩy động ở dạng thập phân hoặc dạng thập lục phân.
Các ký tự dấu phẩy động thập phân bao gồm một chuỗi các chữ số thập phân theo sau là một phân số thập phân, một số mũ thập phân hoặc cả hai.
Các ký tự dấu phẩy động hệ thập lục phân bao gồm tiền tố 0x, theo sau là phân số thập lục phân tùy chọn, theo sau là số mũ thập lục phân.
Dưới đây là một số ví dụ về các ký tự dấu phẩy động -
let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0
Chuỗi chữ
Một chuỗi ký tự là một chuỗi các ký tự được bao quanh bởi dấu ngoặc kép, có dạng sau:
"characters"
Các ký tự chuỗi không được chứa dấu ngoặc kép không thoát ("), dấu gạch chéo ngược không thoát (\), ký tự xuống dòng hoặc nguồn cấp dữ liệu dòng. Các ký tự đặc biệt có thể được đưa vào ký tự chuỗi bằng cách sử dụng các chuỗi thoát sau:
Trình tự thoát | Ý nghĩa |
---|---|
\ 0 | Ký tự rỗng |
\\ | \tính cách |
\ b | Backspace |
\ f | Thức ăn dạng |
\ n | Dòng mới |
\ r | Vận chuyển trở lại |
\ t | Tab ngang |
\ v | Tab dọc |
\ ' | Trích dẫn đơn |
\ " | Trích dẫn kép |
000 | Số bát phân từ một đến ba chữ số |
\ xhh ... | Số thập lục phân gồm một hoặc nhiều chữ số |
Ví dụ sau đây cho thấy cách sử dụng một vài ký tự chuỗi:
let stringL = "Hello\tWorld\n\nHello\'Swift 4\'"
print(stringL)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Hello World
Hello'Swift 4'
Boolean Literals
Có ba ký tự Boolean và chúng là một phần của từ khóa Swift 4 tiêu chuẩn -
Một giá trị của true đại diện cho sự thật.
Một giá trị của false đại diện cho sai.
Một giá trị của nil đại diện cho không có giá trị.
Một toán tử là một ký hiệu yêu cầu trình biên dịch thực hiện các thao tác toán học hoặc logic cụ thể. Objective-C có nhiều toán tử cài sẵn và cung cấp các loại toán tử sau:
- Toán tử số học
- Toán tử so sánh
- Toán tử logic
- Toán tử Bitwise
- Người điều hành nhiệm vụ
- Toán tử phạm vi
- Nhà điều hành khác
Hướng dẫn này sẽ giải thích từng toán tử số học, quan hệ, logic, bitwise, phép gán và các toán tử khác.
Toán tử số học
Bảng sau đây cho thấy tất cả các toán tử số học được ngôn ngữ Swift 4 hỗ trợ. Giả sử biếnA giữ 10 và biến B giữ 20, sau đó -
Nhà điều hành | Sự miêu tả | Thí dụ |
---|---|---|
+ | Thêm hai toán hạng | A + B sẽ cho 30 |
- | Trừ toán hạng thứ hai với toán hạng đầu tiên | A - B sẽ cho -10 |
* | Nhân cả hai toán hạng | A * B sẽ cho 200 |
/ | Chia tử số cho mẫu số | B / A sẽ cho 2 |
% | Toán tử mô đun và phần còn lại của sau một phép chia số nguyên / float | B% A sẽ cho 0 |
Toán tử so sánh
Bảng sau đây cho thấy tất cả các toán tử quan hệ được ngôn ngữ Swift 4 hỗ trợ. Giả sử biếnA giữ 10 và biến B giữ 20, sau đó -
Nhà điều hành | Sự miêu tả | Thí dụ |
---|---|---|
== | Kiểm tra xem giá trị của hai toán hạng có bằng nhau hay không; nếu có, thì điều kiện trở thành đúng. | (A == B) không đúng. |
! = | Kiểm tra xem giá trị của hai toán hạng có bằng nhau hay không; nếu các giá trị không bằng nhau, thì điều kiện trở thành true. | (A! = B) là đúng. |
> | Kiểm tra xem giá trị của toán hạng bên trái có lớn hơn giá trị của toán hạng bên phải hay không; nếu có, thì điều kiện trở thành đúng. | (A> B) là không đúng. |
< | Kiểm tra nếu giá trị của toán hạng bên trái nhỏ hơn giá trị của toán hạng bên phải; nếu có, thì điều kiện trở thành đúng. | (A <B) là đúng. |
> = | Kiểm tra nếu giá trị của toán hạng bên trái lớn hơn hoặc bằng giá trị của toán hạng bên phải; nếu có, thì điều kiện trở thành đúng. | (A> = B) là không đúng. |
<= | Kiểm tra nếu giá trị của toán hạng bên trái nhỏ hơn hoặc bằng giá trị của toán hạng bên phải; nếu có, thì điều kiện trở thành đúng. | (A <= B) là đúng. |
Toán tử logic
Bảng sau đây cho thấy tất cả các toán tử logic được hỗ trợ bởi ngôn ngữ Swift 4. Giả sử biếnA giữ 1 và biến B giữ 0, sau đó -
Nhà điều hành | Sự miêu tả | Thí dụ |
---|---|---|
&& | Được gọi là toán tử logic AND. Nếu cả hai toán hạng đều khác 0, thì điều kiện trở thành true. | (A && B) là sai. |
|| | Được gọi là Toán tử logic HOẶC. Nếu bất kỳ toán hạng nào trong hai toán hạng khác 0, thì điều kiện trở thành true. | (A || B) là đúng. |
! | Called Logical NOT Operator. Use to reverses the logical state of its operand. If a condition is true, then the Logical NOT operator will make it false. | !(A && B) is true. |
Bitwise Operators
Bitwise operators work on bits and perform bit by bit operation. The truth tables for &, |, and ^ are as follows −
p | q | p&q | p|q | p^q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
Assume A = 60; and B = 13;
In binary format, they will be as follows:
A = 0011 1100
B = 0000 1101
-----------------
A & B = 0000 1100
A|B = 0011 1101
A^B = 0011 0001
~A = 1100 0011
Bitwise operators supported by Swift 4 language are listed in the following table. Assume variable A holds 60 and variable B holds 13, then 7−
Operator | Description | Example |
---|---|---|
& | Binary AND Operator copies a bit to the result, if it exists in both operands. | (A & B) will give 12, which is 0000 1100 |
| | Binary OR Operator copies a bit, if it exists in either operand. | (A | B) will give 61, which is 0011 1101 |
^ | Binary XOR Operator copies the bit, if it is set in one operand but not both. | (A ^ B) will give 49, which is 0011 0001 |
~ | Binary Ones Complement Operator is unary and has the effect of 'flipping' bits. | (~A ) will give -61, which is 1100 0011 in 2's complement form. |
<< | Binary Left Shift Operator. The left operands value is moved left by the number of bits specified by the right operand. | (A << 2 will give 240, which is 1111 0000 |
>> | Binary Right Shift Operator. The left operands value is moved right by the number of bits specified by the right operand. | A >> 2 will give 15, which is 0000 1111 |
Assignment Operators
SSwift 4 supports the following assignment operators −
Operator | Description | Example |
---|---|---|
= | Simple assignment operator, Assigns values from right side operands to left side operand | C = A + B will assign value of A + B into C |
+= | Add AND assignment operator, It adds right operand to the left operand and assigns the result to left operand | C += A is equivalent to C = C + A |
-= | Subtract AND assignment operator, It subtracts right operand from the left operand and assigns the result to left operand | C -= A is equivalent to C = C - A |
*= | Multiply AND assignment operator, It multiplies right operand with the left operand and assigns the result to left operand | C *= A is equivalent to C = C * A |
/= | Divide AND assignment operator, It divides left operand with the right operand and assigns the result to left operand | C /= A is equivalent to C = C / A |
%= | Modulus AND assignment operator, It takes modulus using two operands and assigns the result to left operand | C %= A is equivalent to C = C % A |
<<= | Left shift AND assignment operator | C <<= 2 is same as C = C << 2 |
>>= | Right shift AND assignment operator | C >>= 2 is same as C = C >> 2 |
&= | Bitwise AND assignment operator | C &= 2 is same as C = C & 2 |
^= | bitwise exclusive OR and assignment operator | C ^= 2 is same as C = C ^ 2 |
|= | bitwise inclusive OR and assignment operator | C |= 2 is same as C = C | 2 |
Range Operators
Swift 4 includes two range operators, which are shortcuts for expressing a range of values. The following table explains these two operators.
Operator | Description | Example |
---|---|---|
Closed Range | (a...b) defines a range that runs from a to b, and includes the values a and b. | 1...5 gives 1, 2, 3, 4 and 5 |
Half-Open Range | (a..< b) defines a range that runs from a to b, but does not include b. | 1..< 5 gives 1, 2, 3, and 4 |
One- sided Range | a… , defines a range that runs from a to end of elements …a , defines a range starting from start to a |
1… gives 1 , 2,3… end of elements …2 gives beginning… to 1,2 |
Misc Operators
Swift 4 supports a few other important operators including range and ? : which are explained in the following table.
Operator | Description | Example |
---|---|---|
Unary Minus | The sign of a numeric value can be toggled using a prefixed - | -3 or -4 |
Unary Plus | Returns the value it operates on, without any change. | +6 gives 6 |
Ternary Conditional | Condition ? X : Y | If Condition is true ? Then value X : Otherwise value Y |
Operators Precedence
Operator precedence determines the grouping of terms in an expression. This affects how an expression is evaluated. Certain operators have higher precedence than others; for example, the multiplication operator has higher precedence than the addition operator.
For example, x = 7 + 3 * 2; here, x is assigned 13, not 20 because operator * has higher precedence than +, so it first gets multiplied with 3*2 and then adds into 7.
Here, operators with the highest precedence appear at the top of the table, those with the lowest appear at the bottom. Within an expression, higher precedence operators will be evaluated first.
Operator | Description | Example |
---|---|---|
Primary Expression Operators | () [] . expr++ expr-- | left-to-right |
Unary Operators | * & + - ! ~ ++expr --expr * / % + - >> << < > <= >= == != |
right-to-left |
Binary Operators | & ^ | && || |
left-to-right |
Ternary Operator | ?: | right-to-left |
Assignment Operators | = += -= *= /= %= >>= <<= &=^= |= | right-to-left |
Comma | , | left-to-right |
Decision making structures require that the programmer specifies one or more conditions to be evaluated or tested by the program, along with a statement or statements to be executed if the condition is determined to be true, and optionally, other statements to be executed if the condition is determined to be false.
Following is the general from of a typical decision making structure found in most of the programming languages −
Swift 4 provides the following types of decision making statements. Click the following links to check their detail.
Sr.No | Statement & Description |
---|---|
1 | if statement An if statement consists of a Boolean expression followed by one or more statements. |
2 | if...else statement An if statement can be followed by an optional else statement, which executes when the Boolean expression is false. |
3 | if...else if...else Statement An if statement can be followed by an optional else if...else statement, which is very useful to test various conditions using single if...else if statement. |
4 | nested if statements You can use one if or else if statement inside another if or else if statement(s). |
5 | switch statement A switch statement allows a variable to be tested for equality against a list of values. |
The ? : Operator
We have covered conditional operator ? : in the previous chapter which can be used to replace if...else statements. It has the following general form −
Exp1 ? Exp2 : Exp3;
Where Exp1, Exp2, and Exp3 are expressions. Notice the use and placement of the colon.
The value of a ? expression is determined like this: Exp1 is evaluated. If it is true, then Exp2 is evaluated and becomes the value of the entire ? expression. If Exp1 is false, then Exp3 is evaluated and its value becomes the value of the expression.
There may be a situation when you need to execute a block of code several number of times. In general, statements are executed sequentially: The first statement in a function is executed first, followed by the second, and so on.
Programming languages provide various control structures that allow for more complicated execution paths.
A loop statement allows us to execute a statement or group of statements multiple times. Following is the general from of a loop statement in most of the programming languages −
Swift 4 programming language provides the following kinds of loop to handle looping requirements. Click the following links to check their detail.
Sr.No | Loop Type & Description |
---|---|
1 | for-in This loop performs a set of statements for each item in a range, sequence, collection, or progression. |
2 | while loop Repeats a statement or group of statements while a given condition is true. It tests the condition before executing the loop body. |
3 | repeat...while loop Like a while statement, except that it tests the condition at the end of the loop body. |
Loop Control Statements
Loop control statements change execution from its normal sequence. When execution leaves a scope, all automatic objects that were created in that scope are destroyed.
Swift 4 supports the following control statements. Click the following links to check their detail.
Sr.No | Control Statement & Description |
---|---|
1 | continue statement This statement tells a loop to stop what it is doing and start again at the beginning of the next iteration through the loop. |
2 | break statement Terminates the loop statement and transfers execution to the statement immediately following the loop. |
3 | fallthrough statement The fallthrough statement simulates the behavior of Swift 4 switch to C-style switch. |
Strings in Swift 4 are an ordered collection of characters, such as "Hello, World!" and they are represented by the Swift 4 data type String, which in turn represents a collection of values of Character type.
Create a String
You can create a String either by using a string literal or creating an instance of a String class as follows −
// String creation using String literal
var stringA = "Hello, Swift 4!"
print( stringA )
// String creation using String instance
var stringB = String("Hello, Swift 4!")
print( stringB )
//Multiple line string
let stringC = """
Hey this is a
example of multiple Line
string by tutorialsPoint
"""
print(stringC)
When the above code is compiled and executed, it produces the following result
Hello, Swift 4!
Hello, Swift 4!
Hey this is a
example of multiple Line
string by tutorialsPoint
Empty String
You can create an empty String either by using an empty string literal or creating an instance of String class as shown below. You can also check whether a string is empty or not using the Boolean property isEmpty.
// Empty string creation using String literal
var stringA = ""
if stringA.isEmpty {
print( "stringA is empty" )
} else {
print( "stringA is not empty" )
}
// Empty string creation using String instance
let stringB = String()
if stringB.isEmpty {
print( "stringB is empty" )
} else {
print( "stringB is not empty" )
}
When the above code is compiled and executed, it produces the following result −
stringA is empty
stringB is empty
String Constants
You can specify whether your String can be modified (or mutated) by assigning it to a variable, or it will be constant by assigning it to a constant using let keyword as shown below −
// stringA can be modified
var stringA = "Hello, Swift 4!"
stringA + = "--Readers--"
print( stringA )
// stringB can not be modified
let stringB = String("Hello, Swift 4!")
stringB + = "--Readers--"
print( stringB )
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Playground execution failed: error: <EXPR>:10:1: error: 'String' is not
convertible to '@lvalue UInt8'
stringB + = "--Readers--"
Nội suy chuỗi
Nội suy chuỗi là một cách để xây dựng một giá trị Chuỗi mới từ hỗn hợp các hằng số, biến, ký tự và biểu thức bằng cách bao gồm các giá trị của chúng bên trong một ký tự chuỗi.
Mỗi mục (biến hoặc hằng số) mà bạn chèn vào chuỗi ký tự được bao bọc trong một cặp dấu ngoặc đơn, bắt đầu bằng dấu gạch chéo ngược. Đây là một ví dụ đơn giản -
var varA = 20
let constA = 100
var varC:Float = 20.0
var stringA = "\(varA) times \(constA) is equal to \(varC * 100)"
print( stringA )
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
20 times 100 is equal to 2000.0
Kết nối chuỗi
Bạn có thể sử dụng toán tử + để nối hai chuỗi hoặc một chuỗi và một ký tự hoặc hai ký tự. Đây là một ví dụ đơn giản -
let constA = "Hello,"
let constB = "World!"
var stringA = constA + constB
print( stringA )
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Hello,World!
Chiều dài chuỗi
Swift 4 chuỗi không có lengthnhưng bạn có thể sử dụng hàm count () toàn cục để đếm số ký tự trong một chuỗi. Đây là một ví dụ đơn giản -
var varA = "Hello, Swift 4!"
print( "\(varA), length is \((varA.count))" )
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Hello, Swift 4!, length is 15
So sánh chuỗi
Bạn có thể sử dụng toán tử == để so sánh hai biến chuỗi hoặc hằng số. Đây là một ví dụ đơn giản -
var varA = "Hello, Swift 4!"
var varB = "Hello, World!"
if varA == varB {
print( "\(varA) and \(varB) are equal" )
} else {
print( "\(varA) and \(varB) are not equal" )
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Hello, Swift 4! and Hello, World! are not equal
Lặp lại chuỗi
Các chuỗi lại là một tập hợp các giá trị trong swift 4, vì vậy chúng ta có thể lặp qua chuỗi bằng cách sử dụng các vòng lặp. -
for chars in "ThisString" {
print(chars, terminator: " ")
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
T h i s S t r i n g
Chuỗi Unicode
Bạn có thể truy cập biểu diễn UTF-8 và UTF-16 của một Chuỗi bằng cách lặp qua các thuộc tính utf8 và utf16 của nó như được minh họa trong ví dụ sau:
var unicodeString = "Dog???"
print("UTF-8 Codes: ")
for code in unicodeString.utf8 {
print("\(code) ")
}
print("\n")
print("UTF-16 Codes: ")
for code in unicodeString.utf16 {
print("\(code) ")
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
UTF-8 Codes:
68
111
103
63
63
63
UTF-16 Codes:
68
111
103
63
63
63
Các hàm & toán tử chuỗi
Swift 4 hỗ trợ một loạt các phương thức và toán tử liên quan đến Chuỗi -
Sr.No | Chức năng / Người vận hành & Mục đích |
---|---|
1 | isEmpty Giá trị Boolean xác định xem một chuỗi có trống hay không. |
2 | hasPrefix(prefix: String) Hàm để kiểm tra xem một chuỗi tham số đã cho có tồn tại dưới dạng tiền tố của chuỗi hay không. |
3 | hasSuffix(suffix: String) Hàm để kiểm tra xem một chuỗi tham số đã cho có tồn tại dưới dạng hậu tố của chuỗi hay không. |
4 | toInt() Hàm chuyển giá trị Chuỗi số thành Số nguyên. |
5 | count() Hàm toàn cục để đếm số ký tự trong một chuỗi. |
6 | utf8 Thuộc tính trả về biểu diễn UTF-8 của một chuỗi. |
7 | utf16 Thuộc tính trả về biểu diễn UTF-16 của một chuỗi. |
số 8 | unicodeScalars Thuộc tính trả về biểu diễn Unicode Scalar của một chuỗi. |
9 | + Toán tử để nối hai chuỗi, hoặc một chuỗi và một ký tự, hoặc hai ký tự. |
10 | += Toán tử để nối một chuỗi hoặc ký tự vào một chuỗi hiện có. |
11 | == Toán tử để xác định bằng nhau của hai chuỗi. |
12 | < Toán tử để thực hiện so sánh từ điển để xác định xem một chuỗi có đánh giá thấp hơn chuỗi khác hay không. |
13 | startIndex Để nhận giá trị tại chỉ mục bắt đầu của chuỗi. |
14 | endIndex Để nhận giá trị tại chỉ mục kết thúc của chuỗi. |
15 | Indices Để truy cập từng phần một. tức là tất cả các ký tự của chuỗi từng cái một. |
16 | insert("Value", at: position) Để chèn một giá trị tại một vị trí. |
17 | remove(at: position) removeSubrange(range) để xóa một giá trị tại một vị trí hoặc để xóa một dải giá trị khỏi chuỗi. |
18 | reversed() trả về mặt sau của một chuỗi |
A character trong Swift là một chuỗi ký tự đơn, được đánh địa chỉ bởi kiểu dữ liệu Character. Hãy xem ví dụ sau. Nó sử dụng hai hằng ký tự -
let char1: Character = "A"
let char2: Character = "B"
print("Value of char1 \(char1)")
print("Value of char2 \(char2)")
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Value of char1 A
Value of char2 B
Nếu bạn cố gắng lưu trữ nhiều hơn một ký tự trong một biến kiểu ký tự hoặc hằng số, thì Swift 4 sẽ không cho phép điều đó. Hãy thử gõ ví dụ sau vào Swift 4 Playground và bạn sẽ gặp lỗi ngay cả trước khi biên dịch.
// Following is wrong in Swift 4
let char: Character = "AB"
print("Value of char \(char)")
Biến ký tự trống
Không thể tạo một biến Ký tự trống hoặc hằng số sẽ có giá trị trống. Cú pháp sau không thể thực hiện được:
// Following is wrong in Swift 4
let char1: Character = ""
var char2: Character = ""
print("Value of char1 \(char1)")
print("Value of char2 \(char2)")
Truy cập các ký tự từ chuỗi
Như đã giải thích khi thảo luận về Chuỗi của Swift 4, Chuỗi đại diện cho một tập hợp các giá trị Ký tự theo một thứ tự được chỉ định. Vì vậy, chúng tôi có thể truy cập các ký tự riêng lẻ từ Chuỗi đã cho bằng cách lặp lại chuỗi đó vớifor-in vòng lặp -
for ch in "Hello" {
print(ch)
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
H
e
l
l
o
Nối các chuỗi với các ký tự
Ví dụ sau minh họa cách một Ký tự của Swift 4 có thể được nối với Chuỗi của Swift 4.
var varA:String = "Hello "
let varB:Character = "G"
varA.append( varB )
print("Value of varC = \(varA)")
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Value of varC = Hello G
Mảng Swift 4 được sử dụng để lưu trữ danh sách có thứ tự các giá trị cùng kiểu. Swift 4 kiểm tra nghiêm ngặt để không cho phép bạn nhập sai kiểu trong một mảng, thậm chí do nhầm lẫn.
Nếu bạn gán một mảng đã tạo cho một biến, thì nó luôn có thể thay đổi được, có nghĩa là bạn có thể thay đổi nó bằng cách thêm, bớt hoặc thay đổi các mục của nó; nhưng nếu bạn gán một mảng cho một hằng số, thì mảng đó là bất biến và không thể thay đổi kích thước và nội dung của nó.
Tạo Mảng
Bạn có thể tạo một mảng trống thuộc một loại nhất định bằng cách sử dụng cú pháp trình khởi tạo sau:
var someArray = [SomeType]()
Đây là cú pháp để tạo một mảng có kích thước cho trước a * và khởi tạo nó với giá trị -
var someArray = [SomeType](count: NumbeOfElements, repeatedValue: InitialValue)
Bạn có thể sử dụng câu lệnh sau để tạo một mảng trống Int loại có 3 phần tử và giá trị ban đầu là 0 -
var someInts = [Int](count: 3, repeatedValue: 0)
Sau đây là một ví dụ khác để tạo một mảng ba phần tử và gán ba giá trị cho mảng đó:
var someInts:[Int] = [10, 20, 30]
Truy cập Mảng
Bạn có thể lấy một giá trị từ một mảng bằng cách sử dụng subscript cú pháp, chuyển chỉ mục của giá trị bạn muốn lấy trong dấu ngoặc vuông ngay sau tên của mảng như sau:
var someVar = someArray[index]
Đây, indexbắt đầu từ 0 có nghĩa là phần tử đầu tiên có thể được truy cập bằng chỉ mục là 0, phần tử thứ hai có thể được truy cập bằng chỉ mục là 1, v.v. Ví dụ sau đây cho thấy cách tạo, khởi tạo và truy cập mảng:
var someInts = [Int](count: 3, repeatedValue: 10)
var someVar = someInts[0]
print( "Value of first element is \(someVar)" )
print( "Value of second element is \(someInts[1])" )
print( "Value of third element is \(someInts[2])" )
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Value of first element is 10
Value of second element is 10
Value of third element is 10
Sửa đổi mảng
Bạn có thể dùng append()phương thức hoặc toán tử gán phép cộng (+ =) để thêm một mục mới vào cuối mảng. Hãy xem ví dụ sau. Ở đây, ban đầu, chúng tôi tạo một mảng trống và sau đó thêm các phần tử mới vào cùng một mảng -
var someInts = [Int]()
someInts.append(20)
someInts.append(30)
someInts += [40]
var someVar = someInts[0]
print( "Value of first element is \(someVar)" )
print( "Value of second element is \(someInts[1])" )
print( "Value of third element is \(someInts[2])" )
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Value of first element is 20
Value of second element is 30
Value of third element is 40
Bạn có thể sửa đổi một phần tử hiện có của một Mảng bằng cách gán một giá trị mới tại một chỉ mục nhất định như thể hiện trong ví dụ sau:
var someInts = [Int]()
someInts.append(20)
someInts.append(30)
someInts += [40]
// Modify last element
someInts[2] = 50
var someVar = someInts[0]
print( "Value of first element is \(someVar)" )
print( "Value of second element is \(someInts[1])" )
print( "Value of third element is \(someInts[2])" )
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Value of first element is 20
Value of second element is 30
Value of third element is 50
Lặp lại trên một mảng
Bạn có thể dùng for-in vòng lặp để lặp lại toàn bộ tập giá trị trong một mảng như được hiển thị trong ví dụ sau:
var someStrs = [String]()
someStrs.append("Apple")
someStrs.append("Amazon")
someStrs += ["Google"]
for item in someStrs {
print(item)
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Apple
Amazon
Google
Bạn có thể dùng enumerate() hàm trả về chỉ mục của một mục cùng với giá trị của nó như được hiển thị bên dưới trong ví dụ sau:
var someStrs = [String]()
someStrs.append("Apple")
someStrs.append("Amazon")
someStrs += ["Google"]
for (index, item) in someStrs.enumerated() {
print("Value at index = \(index) is \(item)")
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Value at index = 0 is Apple
Value at index = 1 is Amazon
Value at index = 2 is Google
Thêm hai mảng
Bạn có thể sử dụng toán tử cộng (+) để thêm hai mảng cùng kiểu sẽ tạo ra một mảng mới với sự kết hợp các giá trị từ hai mảng như sau:
var intsA = [Int](count:2, repeatedValue: 2)
var intsB = [Int](count:3, repeatedValue: 1)
var intsC = intsA + intsB
for item in intsC {
print(item)
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
2
2
1
1
1
Thuộc tính đếm
Bạn có thể sử dụng chế độ chỉ đọc count thuộc tính của một mảng để tìm ra số lượng các mục trong một mảng được hiển thị bên dưới:
var intsA = [Int](count:2, repeatedValue: 2)
var intsB = [Int](count:3, repeatedValue: 1)
var intsC = intsA + intsB
print("Total items in intsA = \(intsA.count)")
print("Total items in intsB = \(intsB.count)")
print("Total items in intsC = \(intsC.count)")
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Total items in intsA = 2
Total items in intsB = 3
Total items in intsC = 5
Thuộc tính trống
Bạn có thể sử dụng chế độ chỉ đọc empty thuộc tính của một mảng để tìm xem một mảng có trống hay không như hình dưới đây:
var intsA = [Int](count:2, repeatedValue: 2)
var intsB = [Int](count:3, repeatedValue: 1)
var intsC = [Int]()
print("intsA.isEmpty = \(intsA.isEmpty)")
print("intsB.isEmpty = \(intsB.isEmpty)")
print("intsC.isEmpty = \(intsC.isEmpty)")
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
intsA.isEmpty = false
intsB.isEmpty = false
intsC.isEmpty = true
Swift 4 sets được sử dụng để lưu trữ các giá trị riêng biệt của cùng một kiểu nhưng chúng không có thứ tự nhất định như mảng có.
Bạn có thể sử dụng tập hợp thay vì mảng nếu thứ tự của các phần tử không phải là vấn đề hoặc nếu bạn muốn đảm bảo rằng không có giá trị trùng lặp. (các bộ chỉ cho phép các giá trị riêng biệt.)
Một loại phải có thể băm để được lưu trữ trong một tập hợp. Giá trị băm là một giá trị Int bằng nhau cho các đối tượng bằng nhau. Ví dụ: nếu x == y, thìx.hashvalue == y.hashvalue.
Tất cả các giá trị nhanh cơ bản là loại có thể băm theo mặc định và có thể được sử dụng làm giá trị đã đặt.
Tạo bộ
Bạn có thể tạo một tập hợp trống của một loại nhất định bằng cách sử dụng cú pháp trình khởi tạo sau:
var someSet = Set<Character>() //Character can be replaced by data type of set.
Truy cập và sửa đổi Bộ
Bạn có thể truy cập hoặc sửa đổi một tập hợp bằng các phương thức và thuộc tính của nó -
Phương thức "count" có thể được sử dụng để hiển thị số phần tử trong tập hợp.
someSet.count // prints the number of elements
Phương thức "insert" có thể được sử dụng để chèn các giá trị trong tập hợp.
someSet.insert("c") // adds the element to Set.
Tương tự, isEmpty có thể được sử dụng để kiểm tra xem set có trống hay không.
someSet.isEmpty // returns true or false depending on the set Elements.
Phương thức "remove" có thể được sử dụng để xóa giá trị trong tập hợp.
someSet.remove("c") // removes a element , removeAll() can be used to remove all elements
Phương thức "chứa" có thể được sử dụng để kiểm tra sự tồn tại của giá trị trong một tập hợp.
someSet.contains("c") // to check if set contains this value.
Lặp lại trên một tập hợp
Bạn có thể lặp lại một tập hợp bằng vòng lặp for-in -
for items in someSet {
print(someSet)
}
//Swift sets are not in an ordered way, to iterate over a set in ordered way use
for items in someSet.sorted() {
print(someSet)
}
Thực hiện các hoạt động tập hợp
Bạn có thể thực hiện các thao tác thiết lập cơ bản trên Bộ nhanh.
Sau đây là các phương pháp để thực hiện các hoạt động tập hợp:
- Intersection
- Union
- subtracting
let evens: Set = [10,12,14,16,18]
let odds: Set = [5,7,9,11,13]
let primes = [2,3,5,7]
odds.union(evens).sorted()
// [5,7,9,10,11,12,13,14,16,18]
odds.intersection(evens).sorted()
//[]
odds.subtracting(primes).sorted()
//[9, 11, 13]
Swift 4 dictionariesđược sử dụng để lưu trữ danh sách không có thứ tự các giá trị cùng loại. Swift 4 thực hiện việc kiểm tra nghiêm ngặt để không cho phép bạn nhập sai loại từ điển ngay cả khi nhập nhầm.
Từ điển Swift 4 sử dụng mã định danh duy nhất được gọi là keyđể lưu trữ một giá trị mà sau này có thể được tham chiếu và tra cứu thông qua cùng một khóa. Không giống như các mục trong một mảng, các mục trong mộtdictionarykhông có một thứ tự xác định. Bạn có thể sử dụng mộtdictionary khi bạn cần tra cứu các giá trị dựa trên số nhận dạng của chúng.
Khóa từ điển có thể là một số nguyên hoặc một chuỗi không có giới hạn, nhưng nó phải là duy nhất trong từ điển.
Nếu bạn gán một từ điển đã tạo cho một biến, thì nó luôn có thể thay đổi, nghĩa là bạn có thể thay đổi nó bằng cách thêm, bớt hoặc thay đổi các mục của nó. Nhưng nếu bạn gán một từ điển cho một hằng số, thì từ điển đó là bất biến và không thể thay đổi kích thước và nội dung của từ điển.
Tạo từ điển
Bạn có thể tạo một từ điển trống của một loại nhất định bằng cách sử dụng cú pháp trình khởi tạo sau:
var someDict = [KeyType: ValueType]()
Bạn có thể sử dụng cú pháp đơn giản sau để tạo một từ điển trống có khóa sẽ là kiểu Int và các giá trị liên quan sẽ là chuỗi -
var someDict = [Int: String]()
Đây là một ví dụ để tạo từ điển từ một tập hợp các giá trị đã cho -
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
Khởi tạo dựa trên trình tự
Swift 4 cho phép bạn tạo Từ điển từ mảng (Cặp khóa-giá trị.)
var cities = [“Delhi”,”Bangalore”,”Hyderabad”]
Bạn có thể sử dụng cú pháp đơn giản sau để tạo một từ điển trống có khóa sẽ là kiểu Int và các giá trị liên quan sẽ là chuỗi -
var Distance = [2000,10, 620]
Đây là một ví dụ để tạo từ điển từ một tập hợp các giá trị đã cho -
let cityDistanceDict = Dictionary(uniqueKeysWithValues: zip(cities, Distance))
Các dòng mã trên sẽ tạo một từ điển với Thành phố là khóa và Khoảng cách là Giá trị -
Lọc
Swift 4 cho phép bạn lọc các giá trị từ từ điển.
var closeCities = cityDistanceDict.filter { $0.value < 1000 }
Nếu chúng ta chạy đoạn mã trên, Từ điển closeCities của chúng ta sẽ được.
["Bangalore" : 10 , "Hyderabad" : 620]
Nhóm từ điển
Swift 4 cho phép bạn tạo nhóm các giá trị Từ điển.
var cities = ["Delhi","Bangalore","Hyderabad","Dehradun","Bihar"]
Bạn có thể sử dụng cú pháp đơn giản sau để nhóm các giá trị của từ điển theo bảng chữ cái đầu tiên.
var GroupedCities = Dictionary(grouping: cities ) { $0.first! }
Kết quả của đoạn mã trên sẽ là
["D" :["Delhi","Dehradun"], "B" : ["Bengaluru","Bihar"], "H" : ["Hyderabad"]]
Truy cập từ điển
Bạn có thể truy xuất một giá trị từ từ điển bằng cách sử dụng cú pháp chỉ số con, chuyển khóa của giá trị bạn muốn truy xuất trong dấu ngoặc vuông ngay sau tên của từ điển như sau:
var someVar = someDict[key]
Hãy kiểm tra ví dụ sau để tạo, khởi tạo và truy cập các giá trị từ từ điển -
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var someVar = someDict[1]
print( "Value of key = 1 is \(someVar)" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Value of key = 1 is Optional("One")
Value of key = 2 is Optional("Two")
Value of key = 3 is Optional("Three")
Sửa đổi từ điển
Bạn có thể dùng updateValue(forKey:)để thêm một giá trị hiện có vào một khóa nhất định của từ điển. Phương thức này trả về một giá trị tùy chọn của kiểu giá trị của từ điển. Đây là một ví dụ đơn giản -
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var oldVal = someDict.updateValue("New value of one", forKey: 1)
var someVar = someDict[1]
print( "Old value of key = 1 is \(oldVal)" )
print( "Value of key = 1 is \(someVar)" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Old value of key = 1 is Optional("One")
Value of key = 1 is Optional("New value of one")
Value of key = 2 is Optional("Two")
Value of key = 3 is Optional("Three")
Bạn có thể sửa đổi một phần tử hiện có của từ điển bằng cách gán giá trị mới tại một khóa nhất định như thể hiện trong ví dụ sau:
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var oldVal = someDict[1]
someDict[1] = "New value of one"
var someVar = someDict[1]
print( "Old value of key = 1 is \(oldVal)" )
print( "Value of key = 1 is \(someVar)" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Old value of key = 1 is Optional("One")
Value of key = 1 is Optional("New value of one")
Value of key = 2 is Optional("Two")
Value of key = 3 is Optional("Three")
Xóa các cặp khóa-giá trị
Bạn có thể dùng removeValueForKey()để xóa một cặp khóa-giá trị khỏi từ điển. Phương thức này loại bỏ cặp khóa-giá trị nếu nó tồn tại và trả về giá trị đã loại bỏ hoặc trả về nil nếu không có giá trị nào tồn tại. Đây là một ví dụ đơn giản -
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var removedValue = someDict.removeValue(forKey: 2)
print( "Value of key = 1 is \(someDict[1])" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Value of key = 1 is Optional("One")
Value of key = 2 is nil
Value of key = 3 is Optional("Three")
Bạn cũng có thể sử dụng cú pháp chỉ số con để xóa cặp khóa-giá trị khỏi từ điển bằng cách gán giá trị nilcho khóa đó. Đây là một ví dụ đơn giản -
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
someDict[2] = nil
print( "Value of key = 1 is \(someDict[1])" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Value of key = 1 is Optional("One")
Value of key = 2 is nil
Value of key = 3 is Optional("Three")
Lặp lại từ điển
Bạn có thể sử dụng một for-in lặp để lặp lại toàn bộ tập hợp các cặp khóa-giá trị trong Từ điển như được hiển thị trong ví dụ sau:
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
for (index, keyValue) in someDict.enumerated() {
print("Dictionary key \(index) - Dictionary value \(keyValue)")
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Dictionary key 2 - Dictionary value Two
Dictionary key 3 - Dictionary value Three
Dictionary key 1 - Dictionary value One
Bạn có thể dùng enumerate() hàm trả về chỉ mục của mục cùng với cặp (khóa, giá trị) của nó như được hiển thị bên dưới trong ví dụ:
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
for (key, value) in someDict.enumerated() {
print("Dictionary key \(key) - Dictionary value \(value)")
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Dictionary key 0 - Dictionary value (key: 2, value: "Two")
Dictionary key 1 - Dictionary value (key: 3, value: "Three")
Dictionary key 2 - Dictionary value (key: 1, value: "One")
Chuyển đổi sang Mảng
Bạn có thể trích xuất danh sách các cặp khóa-giá trị từ một từ điển nhất định để xây dựng các mảng riêng biệt cho cả khóa và giá trị. Đây là một ví dụ -
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
let dictKeys = [Int](someDict.keys)
let dictValues = [String](someDict.values)
print("Print Dictionary Keys")
for (key) in dictKeys {
print("\(key)")
}
print("Print Dictionary Values")
for (value) in dictValues {
print("\(value)")
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Print Dictionary Keys
2
3
1
Print Dictionary Values
Two
Three
One
Thuộc tính đếm
Bạn có thể sử dụng chế độ chỉ đọc count thuộc tính của từ điển để tìm ra số lượng mục trong từ điển như hình dưới đây -
var someDict1:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var someDict2:[Int:String] = [4:"Four", 5:"Five"]
print("Total items in someDict1 = \(someDict1.count)")
print("Total items in someDict2 = \(someDict2.count)")
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Total items in someDict1 = 3
Total items in someDict2 = 2
Thuộc tính trống
Bạn có thể sử dụng chế độ chỉ đọc empty thuộc tính của từ điển để tìm xem từ điển có trống hay không, như được hiển thị bên dưới -
var someDict1:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var someDict2:[Int:String] = [4:"Four", 5:"Five"]
var someDict3:[Int:String] = [Int:String]()
print("someDict1 = \(someDict1.isEmpty)")
print("someDict2 = \(someDict2.isEmpty)")
print("someDict3 = \(someDict3.isEmpty)")
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
someDict1 = false
someDict2 = false
someDict3 = true
Hàm là một tập hợp các câu lệnh được tổ chức lại với nhau để thực hiện một nhiệm vụ cụ thể. Một hàm Swift 4 có thể đơn giản như một hàm C đơn giản đến phức tạp như một hàm ngôn ngữ C Objective. Nó cho phép chúng ta truyền các giá trị tham số cục bộ và toàn cục bên trong các lời gọi hàm.
Function Declaration - cho trình biên dịch biết về tên, kiểu trả về và các tham số của hàm.
Function Definition - Nó cung cấp phần thân thực tế của hàm.
Các hàm Swift 4 chứa kiểu tham số và kiểu trả về của nó.
Định nghĩa hàm
Trong Swift 4, một hàm được định nghĩa bởi từ khóa "func". Khi một hàm mới được xác định, nó có thể nhận một hoặc một số giá trị làm 'tham số' đầu vào cho hàm và nó sẽ xử lý các hàm trong phần thân chính và trả lại giá trị cho các hàm dưới dạng đầu ra 'kiểu trả về'.
Mỗi hàm đều có tên hàm, tên này mô tả tác vụ mà hàm thực hiện. Để sử dụng một hàm, bạn "gọi" hàm đó với tên của nó và chuyển các giá trị đầu vào (được gọi là các đối số) phù hợp với kiểu tham số của hàm. Tham số hàm còn được gọi là 'bộ giá trị'.
Các đối số của một hàm phải luôn được cung cấp theo cùng thứ tự với danh sách tham số của hàm và các giá trị trả về được theo sau bởi →.
Cú pháp
func funcname(Parameters) -> returntype {
Statement1
Statement2
---
Statement N
return parameters
}
Hãy xem đoạn mã sau. Tên của học sinh được khai báo dưới dạng chuỗi dữ liệu được khai báo bên trong hàm 'student' và khi hàm được gọi, nó sẽ trả về tên của học sinh.
func student(name: String) -> String {
return name
}
print(student(name: "First Program"))
print(student(name: "About Functions"))
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
First Program
About Functions
Gọi một hàm
Giả sử chúng ta đã xác định một hàm có tên là "display" để xem xét ví dụ để hiển thị các số, một hàm có tên hàm là "display" được khởi tạo trước với đối số "no1" chứa kiểu dữ liệu số nguyên. Sau đó, đối số 'no1' được gán cho đối số 'a', đối số này sau đó sẽ trỏ đến số nguyên cùng kiểu dữ liệu. Bây giờ đối số 'a' được trả về hàm. Ở đây hàm display () sẽ giữ giá trị nguyên và trả về giá trị nguyên khi mỗi lần hàm được gọi.
func display(no1: Int) -> Int {
let a = no1
return a
}
print(display(no1: 100))
print(display(no1: 200))
Khi chúng tôi chạy chương trình trên bằng cách sử dụng sân chơi, chúng tôi nhận được kết quả sau:
100
200
Các thông số và giá trị trả về
Swift 4 cung cấp các tham số hàm linh hoạt và giá trị trả về của nó từ giá trị đơn giản đến phức tạp. Tương tự như C và Objective C, các hàm trong Swift 4 cũng có thể có nhiều dạng.
Các chức năng với các tham số
Một hàm được truy cập bằng cách chuyển các giá trị tham số của nó vào phần thân của hàm. Chúng ta có thể chuyển các giá trị tham số đơn đến nhiều tham số dưới dạng các bộ giá trị bên trong hàm.
func mult(no1: Int, no2: Int) -> Int {
return no1*no2
}
print(mult(no1: 2, no2: 20))
print(mult(no1: 3, no2: 15))
print(mult(no1: 4, no2: 30))
Khi chúng tôi chạy chương trình trên bằng cách sử dụng sân chơi, chúng tôi nhận được kết quả sau:
40
45
120
Chức năng không có tham số
Chúng tôi cũng có thể có các chức năng mà không có bất kỳ tham số nào.
Cú pháp
func funcname() -> datatype {
return datatype
}
Sau đây là một ví dụ có một hàm không có tham số:
func votersname() -> String {
return "Alice"
}
print(votersname())
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Alice
Các chức năng có giá trị trả lại
Các hàm cũng được sử dụng để trả về các giá trị kiểu dữ liệu chuỗi, số nguyên và float dưới dạng các kiểu trả về. Để tìm ra số lớn nhất và nhỏ nhất trong một mảng đã cho, hàm 'ls' được khai báo với các kiểu dữ liệu số nguyên lớn và nhỏ.
Một mảng được khởi tạo để chứa các giá trị số nguyên. Sau đó, mảng được xử lý và mỗi và mọi giá trị trong mảng được đọc và so sánh với giá trị trước đó của nó. Khi giá trị nhỏ hơn giá trị trước đó, nó được lưu trữ trong đối số "small", nếu không nó được lưu trữ trong đối số "large" và các giá trị được trả về bằng cách gọi hàm.
func ls(array: [Int]) -> (large: Int, small: Int) {
var lar = array[0]
var sma = array[0]
for i in array[1..<array.count] {
if i < sma {
sma = i
} else if i > lar {
lar = i
}
}
return (lar, sma)
}
let num = ls(array: [40,12,-5,78,98])
print("Largest number is: \(num.large) and smallest number is: \(num.small)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Largest number is: 98 and smallest number is: -5
Các chức năng không có giá trị trả lại
Một số hàm có thể có các đối số được khai báo bên trong hàm mà không có bất kỳ giá trị trả về nào. Chương trình sau đây khai báoa và blàm đối số cho hàm sum (). bên trong chính hàm các giá trị cho các đối sốa và b được chuyển bằng cách gọi hàm sum () và các giá trị của nó được in ra do đó loại bỏ các giá trị trả về.
func sum(a: Int, b: Int) {
let a = a + b
let b = a - b
print(a, b)
}
sum(a: 20, b: 10)
sum(a: 40, b: 10)
sum(a: 24, b: 6)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
30 20
50 40
30 24
Chức năng với các loại trả lại tùy chọn
Swift 4 giới thiệu tính năng 'tùy chọn' để giải quyết các vấn đề bằng cách giới thiệu một biện pháp an toàn. Hãy xem xét ví dụ, chúng ta đang khai báo giá trị hàm kiểu trả về là số nguyên nhưng điều gì sẽ xảy ra khi hàm trả về giá trị chuỗi hoặc giá trị nil. Trong trường hợp đó, trình biên dịch sẽ trả về một giá trị lỗi. 'tùy chọn' được giới thiệu để loại bỏ những vấn đề này.
Các hàm tùy chọn sẽ có hai dạng "value" và "nil". Chúng tôi sẽ đề cập đến 'Tùy chọn' với ký tự dành riêng cho khóa '?' để kiểm tra xem bộ tuple đang trả về giá trị hay giá trị nil.
func minMax(array: [Int]) -> (min: Int, max: Int)? {
if array.isEmpty { return nil }
var currentMin = array[0]
var currentMax = array[0]
for value in array[1..<array.count] {
if value < currentMin {
currentMin = value
} else if value > currentMax {
currentMax = value
}
}
return (currentMin, currentMax)
}
if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
print("min is \(bounds.min) and max is \(bounds.max)")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
min is -6 and max is 109
'' Tùy chọn '' được sử dụng để kiểm tra các giá trị 'nil' hoặc rác do đó tiêu tốn nhiều thời gian trong việc gỡ lỗi và làm cho mã hiệu quả và dễ đọc đối với người dùng.
Chức năng Tên thông số bên ngoài Vs cục bộ
Tên tham số cục bộ
Tên tham số cục bộ chỉ được truy cập bên trong hàm.
func sample(number: Int) {
print(number)
}
Đây, funcSố đối số mẫu được khai báo là biến nội bộ vì nó được truy cập nội bộ bởi hàm sample (). Ở đây 'số' được khai báo là biến cục bộ nhưng tham chiếu đến biến được thực hiện bên ngoài hàm với câu lệnh sau:
func sample(number: Int) {
print(number)
}
sample(number: 1)
sample(number: 2)
sample(number: 3)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
1
2
3
Tên thông số bên ngoài
Tên tham số bên ngoài cho phép chúng ta đặt tên cho một tham số hàm để làm cho mục đích của chúng rõ ràng hơn. Ví dụ dưới đây, bạn có thể đặt tên cho hai tham số hàm và sau đó gọi hàm đó như sau:
func pow(firstArg a: Int, secondArg b: Int) -> Int {
var res = a
for _ in 1..<b {
res = res * a
}
print(res)
return res
}
pow(firstArg:5, secondArg:3)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
125
Các thông số đa dạng
Khi chúng ta muốn xác định hàm với nhiều đối số, thì chúng ta có thể khai báo các thành viên là tham số 'variadic'. Các tham số có thể được chỉ định dưới dạng đa dạng bởi (···) sau tên tham số.
func vari<N>(members: N...){
for i in members {
print(i)
}
}
vari(members: 4,3,5)
vari(members: 4.5, 3.1, 5.6)
vari(members: "Swift 4", "Enumerations", "Closures")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
4
3
5
4.5
3.1
5.6
Swift 4
Enumerations
Closures
Các tham số không đổi, biến và I / O
Các hàm theo mặc định coi các tham số là 'hằng số', trong khi người dùng cũng có thể khai báo các đối số cho các hàm dưới dạng biến. Chúng ta đã thảo luận rằng từ khóa 'let' được sử dụng để khai báo các tham số không đổi và các tham số biến được định nghĩa bằng từ khóa 'var'.
Các tham số I / O trong Swift 4 cung cấp chức năng giữ lại các giá trị tham số mặc dù các giá trị của nó được sửa đổi sau khi gọi hàm. Ở phần đầu của định nghĩa tham số hàm, từ khóa 'inout' được khai báo để giữ lại các giá trị thành viên.
Nó dẫn xuất từ khóa 'inout' vì các giá trị của nó được truyền 'vào' cho hàm và các giá trị của nó được truy cập và sửa đổi bởi phần thân hàm của nó và nó được trả về 'out' khỏi hàm để sửa đổi đối số ban đầu.
Các biến chỉ được truyền dưới dạng đối số cho tham số in-out vì chỉ các giá trị của nó được sửa đổi bên trong và bên ngoài hàm. Do đó không cần khai báo chuỗi và ký tự dưới dạng tham số đầu vào. '&' trước tên biến cho biết chúng ta đang chuyển đối số tới tham số in-out.
func temp(a1: inout Int, b1: inout Int) {
let t = a1
a1 = b1
b1 = t
}
var no = 2
var co = 10
temp(a1: &no, b1: &co)
print("Swapped values are \(no), \(co)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Swapped values are 10, 2
Các loại chức năng và cách sử dụng nó
Mỗi và mọi chức năng tuân theo chức năng cụ thể bằng cách xem xét các tham số đầu vào và đưa ra kết quả mong muốn.
func inputs(no1: Int, no2: Int) -> Int {
return no1/no2
}
Sau đây là một ví dụ -
func inputs(no1: Int, no2: Int) -> Int {
return no1/no2
}
print(inputs(no1: 20, no2: 10))
print(inputs(no1: 36, no2: 6))
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
2
6
Ở đây hàm được khởi tạo với hai đối số no1 và no2 là kiểu dữ liệu số nguyên và kiểu trả về của nó cũng được khai báo là 'int'
Func inputstr(name: String) -> String {
return name
}
Ở đây hàm được khai báo là string loại dữ liệu.
Các chức năng cũng có thể có void kiểu dữ liệu và các hàm như vậy sẽ không trả về bất cứ thứ gì.
func inputstr() {
print("Swift 4 Functions")
print("Types and its Usage")
}
inputstr()
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Swift 4 Functions
Types and its Usage
Hàm trên được khai báo là một hàm void không có đối số và không có giá trị trả về.
Sử dụng các loại chức năng
Đầu tiên, các hàm được truyền với các đối số kiểu số nguyên, float hoặc chuỗi và sau đó nó được truyền dưới dạng hằng số hoặc biến cho hàm như được đề cập bên dưới.
var addition: (Int, Int) -> Int = sum
Ở đây tổng là một tên hàm có các biến số nguyên 'a' và 'b' mà bây giờ được khai báo là một biến cho phép cộng tên hàm. Sau đó, cả hàm cộng và hàm đều có cùng số đối số được khai báo dưới dạng kiểu dữ liệu số nguyên và cũng trả về giá trị nguyên dưới dạng tham chiếu.
func sum(a: Int, b: Int) -> Int {
return a + b
}
var addition: (Int, Int) -> Int = sum
print("Result: \(addition(40, 89))")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Result: 129
Các loại chức năng làm loại tham số & loại trả về
Chúng ta cũng có thể truyền chính hàm dưới dạng các kiểu tham số cho một hàm khác.
func sum(a: Int, b: Int) -> Int {
return a + b
}
var addition: (Int, Int) -> Int = sum
print("Result: \(addition(40, 89))")
func another(addition: (Int, Int) -> Int, a: Int, b: Int) {
print("Result: \(addition(a, b))")
}
another(sum, 10, 20)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Result: 129
Result: 30
Các hàm lồng nhau
Một hàm lồng nhau cung cấp cơ sở để gọi hàm bên ngoài bằng cách gọi hàm bên trong.
func calcDecrement(forDecrement total: Int) -> () -> Int {
var overallDecrement = 0
func decrementer() -> Int {
overallDecrement -= total
return overallDecrement
}
return decrementer
}
let decrem = calcDecrement(forDecrement: 30)
print(decrem())
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
-30
Đóng trong Swift 4 tương tự như các hàm khép kín được tổ chức dưới dạng khối và được gọi ở bất kỳ đâu như ngôn ngữ C và Objective C. Các hằng số và các tham chiếu biến được định nghĩa bên trong các hàm được ghi lại và lưu trữ trong các bao đóng. Các hàm được coi là trường hợp đóng đặc biệt và nó có ba dạng sau:
Chức năng toàn cầu | Các hàm lồng nhau | Biểu thức đóng cửa |
---|---|---|
Có một cái tên. Không nắm bắt bất kỳ giá trị nào | Có một cái tên. Ghi lại các giá trị từ chức năng bao quanh | Các khu vực đóng cửa không đặt tên nắm bắt các giá trị từ các khối liền kề |
Các biểu thức đóng trong ngôn ngữ Swift 4 tuân theo các kiểu cú pháp rõ ràng, tối ưu hóa và gọn nhẹ bao gồm.
- Suy ra các kiểu tham số và giá trị trả về từ ngữ cảnh.
- Trả về ngầm định từ các đóng biểu thức đơn.
- Tên đối số viết tắt và
- Cú pháp đóng theo dõi
Cú pháp
Sau đây là một cú pháp chung để định nghĩa bao đóng chấp nhận các tham số và trả về một kiểu dữ liệu:
{
(parameters) −> return type in
statements
}
Sau đây là một ví dụ đơn giản -
let studname = { print("Welcome to Swift Closures") }
studname()
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Welcome to Swift Closures
Đóng sau chấp nhận hai tham số và trả về giá trị Bool:
{
(Int, Int) −> Bool in
Statement1
Statement 2
---
Statement n
}
Sau đây là một ví dụ đơn giản -
let divide = {
(val1: Int, val2: Int) -> Int in
return val1 / val2
}
let result = divide(200, 20)
print (result)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
10
Biểu thức trong Closures
Các hàm lồng nhau cung cấp một cách thuận tiện để đặt tên và xác định các khối mã. Thay vì đại diện cho toàn bộ khai báo hàm và cấu trúc tên được sử dụng để biểu thị các hàm ngắn hơn. Việc biểu diễn hàm trong một câu lệnh ngắn gọn rõ ràng với cú pháp tập trung được thực hiện thông qua các biểu thức đóng.
Chương trình thứ tự tăng dần
Việc sắp xếp một chuỗi được thực hiện nhờ chức năng dành riêng cho khóa Swift 4s "sắp xếp" đã có sẵn trong thư viện chuẩn. Hàm sẽ sắp xếp các chuỗi đã cho theo thứ tự tăng dần và trả về các phần tử trong một mảng mới có cùng kích thước và kiểu dữ liệu được đề cập trong mảng cũ. Mảng cũ vẫn giữ nguyên.
Hai đối số được biểu diễn bên trong hàm đã sắp xếp -
Giá trị của kiểu đã biết được biểu diễn dưới dạng mảng.
Nội dung mảng (Int, Int) và trả về giá trị Boolean (Bool) nếu mảng được sắp xếp đúng, nó sẽ trả về giá trị true nếu không sẽ trả về false.
Một hàm thông thường với chuỗi đầu vào được viết và chuyển đến hàm đã sắp xếp để các chuỗi được sắp xếp thành mảng mới được hiển thị bên dưới:
func ascend(s1: String, s2: String) -> Bool {
return s1 > s2
}
let stringcmp = ascend(s1: "Swift 4", s2: "great")
print (stringcmp)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
true
Mảng ban đầu được sắp xếp cho icecream được cho là "Swift 4" và "great". Hàm sắp xếp mảng được khai báo là kiểu dữ liệu chuỗi và kiểu trả về của nó được đề cập là Boolean. Cả hai chuỗi được so sánh và sắp xếp theo thứ tự tăng dần và được lưu trữ trong một mảng mới. Nếu việc sắp xếp được thực hiện thành công, hàm sẽ trả về một giá trị true, nếu không nó sẽ trả về giá trị false.
Cú pháp biểu thức đóng sử dụng -
- tham số không đổi,
- tham số biến và
- tham số inout.
Biểu thức đóng không hỗ trợ các giá trị mặc định. Các tham số Variadic và Tuples cũng có thể được sử dụng làm kiểu tham số và kiểu trả về.
let sum = {
(no1: Int, no2: Int) -> Int in
return no1 + no2
}
let digits = sum(10, 20)
print(digits)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
30
Các tham số và khai báo kiểu trả về được đề cập trong câu lệnh hàm cũng có thể được biểu diễn bằng hàm biểu thức đóng nội tuyến với từ khóa 'in'. Sau khi khai báo các loại tham số và trả về, từ khóa 'in' được sử dụng để biểu thị rằng phần thân của bao đóng.
Trả về một biểu thức ngầm
Ở đây, kiểu hàm của đối số thứ hai của hàm được sắp xếp làm rõ ràng rằng giá trị Bool phải được trả về bằng cách đóng. Bởi vì phần thân của bao đóng chứa một biểu thức duy nhất (s1> s2) trả về giá trị Bool, nên không có sự mơ hồ và từ khóa trả về có thể được bỏ qua.
Để trả về một câu lệnh Biểu thức đơn trong biểu thức đóng, từ khóa 'return' bị bỏ qua trong phần khai báo của nó.
var count:[Int] = [5, 10, -6, 75, 20]
let descending = count.sorted(by: { n1, n2 in n1 > n2 })
let ascending = count.sorted(by: { n1, n2 in n1 < n2 })
print(descending)
print(ascending)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
[75, 20, 10, 5, -6]
[-6, 5, 10, 20, 75]
Bản thân câu lệnh xác định rõ ràng rằng khi chuỗi1 lớn hơn chuỗi 2 trả về true, ngược lại là false, do đó câu lệnh trả về bị bỏ qua ở đây.
Kiểu đóng cửa đã biết
Xét phép cộng hai số. Chúng ta biết rằng việc bổ sung sẽ trả về kiểu dữ liệu số nguyên. Do đó, các kiểu đóng cửa đã biết được khai báo là:
let sub = {
(no1: Int, no2: Int) -> Int in
return no1 - no2
}
let digits = sub(10, 20)
print(digits)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
-10
Khai báo tên đối số viết tắt là Closures
Swift 4 tự động cung cấp tên đối số viết tắt cho các bao đóng nội tuyến, có thể được sử dụng để tham chiếu đến các giá trị của các đối số của bao đóng bằng tên $ 0, $1, $2, và như vậy.
var shorthand: (String, String) -> String
shorthand = { $1 }
print(shorthand("100", "200"))
Ở đây, $ 0 và $ 1 tham chiếu đến các đối số Chuỗi đầu tiên và thứ hai của bao đóng.
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
200
Swift 4 tạo điều kiện cho người dùng biểu diễn các bao đóng Nội tuyến dưới dạng tên đối số viết tắt bằng cách đại diện cho $ 0, $1, $2 --- $ n.
Danh sách đối số Closures bị bỏ qua trong phần định nghĩa khi chúng ta biểu diễn tên đối số viết tắt bên trong biểu thức đóng. Dựa trên kiểu hàm, tên đối số viết tắt sẽ được dẫn xuất. Vì đối số viết tắt được xác định trong nội dung biểu thức nên từ khóa 'in' bị bỏ qua.
Đóng cửa như các chức năng của nhà điều hành
Swift 4 cung cấp một cách dễ dàng để truy cập các thành viên bằng cách chỉ cung cấp các hàm toán tử dưới dạng các bao đóng. Trong các ví dụ trước, từ khóa 'Bool' được sử dụng để trả về 'true' khi các chuỗi bằng nhau, nếu không nó trả về 'false'.
Biểu thức thậm chí còn đơn giản hơn bởi hàm toán tử trong bao đóng là:
let numb = [98, -20, -30, 42, 18, 35]
var sortedNumbers = numb.sorted ({
(left: Int, right: Int) -> Bool in
return left < right
})
let asc = numb.sorted(<)
print(asc)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
[-30, -20, 18, 35, 42, 98]
Đóng dưới dạng Rơ moóc
Việc chuyển đối số cuối cùng của hàm đến một biểu thức đóng được khai báo với sự trợ giúp của 'Trailing Closures'. Nó được viết bên ngoài hàm () với {}. Việc sử dụng nó là cần thiết khi không thể viết hàm nội tuyến trên một dòng.
reversed = sorted(names) { $0 > $1}
trong đó {$ 0> $ 1} được biểu thị dưới dạng các dấu đóng cuối được khai báo bên ngoài (tên).
import Foundation
var letters = ["North", "East", "West", "South"]
let twoletters = letters.map({
(state: String) -> String in
return state.substringToIndex(advance(state.startIndex, 2)).uppercaseString
})
let stletters = letters.map() {
$0.substringToIndex(advance($0.startIndex, 2)).uppercaseString
}
print(stletters)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
[NO, EA, WE, SO]
Nắm bắt giá trị và loại tham chiếu
Trong Swift 4, việc nắm bắt các giá trị hằng và biến được thực hiện với sự trợ giúp của các bao đóng. Nó tiếp tục tham chiếu và sửa đổi các giá trị cho các hằng số và biến đó bên trong phần thân đóng mặc dù các biến đó không còn tồn tại.
Việc nắm bắt các giá trị hằng và biến có thể đạt được bằng cách sử dụng hàm lồng nhau bằng cách viết hàm với trong phần thân của hàm khác.
Một hàm lồng nhau nắm bắt -
- Đối số hàm bên ngoài.
- Chụp các hằng số và biến được xác định trong hàm Outer.
Trong Swift 4, khi một hằng hoặc một biến được khai báo bên trong một hàm, thì tham chiếu đến các biến đó cũng được tự động tạo ra bằng cách đóng. Nó cũng cung cấp cơ sở để tham chiếu đến nhiều hơn hai biến dưới dạng bao đóng tương tự như sau:
let decrem = calcDecrement(forDecrement: 18)
decrem()
Đây oneDecrement và các biến Decrement đều sẽ trỏ cùng một khối bộ nhớ làm tham chiếu đóng.
func calcDecrement(forDecrement total: Int) -> () -> Int {
var overallDecrement = 100
func decrementer() -> Int {
overallDecrement -= total
print(overallDecrement)
return overallDecrement
}
return decrementer
}
let decrem = calcDecrement(forDecrement: 18)
decrem()
decrem()
decrem()
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
82
64
46
Khi mỗi và mỗi lần hàm bên ngoài calcDecrement được gọi, nó sẽ gọi hàm decmenter () và giảm giá trị đi 18 và trả về kết quả với sự trợ giúp của hàm bên ngoài calcDecrement. Ở đây calcDecrement hoạt động như một sự đóng cửa.
Mặc dù theo mặc định, hàm decmenter () không có bất kỳ đối số nào đóng tham chiếu đến các biến 'totalDecrement' và 'total' bằng cách nắm bắt các giá trị hiện có của nó. Bản sao của các giá trị cho các biến được chỉ định được lưu trữ bằng hàm giảm dần () mới. Swift 4 xử lý các chức năng quản lý bộ nhớ bằng cách cấp phát và giải quyết các không gian bộ nhớ khi các biến không được sử dụng.
Liệt kê là một kiểu dữ liệu do người dùng xác định bao gồm tập hợp các giá trị liên quan. Từ khóaenum được sử dụng để xác định kiểu dữ liệu liệt kê.
Chức năng liệt kê
Cách liệt kê trong Swift 4 cũng giống với cấu trúc của C và Objective C.
Nó được khai báo trong một lớp và các giá trị của nó được truy cập thông qua thể hiện của lớp đó.
Giá trị thành viên ban đầu được xác định bằng cách sử dụng enum intializers.
Chức năng của nó cũng được mở rộng bằng cách đảm bảo chức năng giao thức tiêu chuẩn.
Cú pháp
Các phép liệt kê được giới thiệu 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 enumname {
// enumeration values are described here
}
Ví dụ, bạn có thể xác định một bảng liệt kê cho các ngày trong tuần như sau:
enum DaysofaWeek {
case Sunday
case Monday
---
case Saturday
}
Thí dụ
enum names {
case Swift
case Closures
}
var lang = names.Closures
lang = .Closures
switch lang {
case .Swift:
print("Welcome to Swift")
case .Closures:
print("Welcome to Closures")
default:
print("Introduction")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Welcome to Closures
Kiểu liệt kê Swift 4 không gán giá trị mặc định cho các thành viên của nó như C và Objective C. Thay vào đó, các thành viên được xác định rõ ràng bằng tên kiểu liệt kê của chúng. Tên bảng kê phải bắt đầu bằng chữ in hoa (Ví dụ: enum DaysofaWeek).
var weekDay = DaysofaWeek.Sunday
Ở đây, tên Enumeration 'DaysofaWeek' được gán cho một ngày trong tuần có thể thay đổi. Nó thông báo cho trình biên dịch rằng kiểu dữ liệu thuộc về Sunday sẽ được gán cho các thành viên enum tiếp theo của lớp cụ thể đó. Khi kiểu dữ liệu thành viên enum được xác định, các thành viên có thể được truy cập bằng cách chuyển các giá trị và tính toán thêm.
Liệt kê với Tuyên bố Chuyển đổi
Câu lệnh 'Switch' của Swift 4 cũng tuân theo lựa chọn đa chiều. Chỉ một biến được truy cập tại một thời điểm cụ thể dựa trên điều kiện đã chỉ định. Trường hợp mặc định trong câu lệnh switch được sử dụng để bẫy các trường hợp không xác định.
enum Climate {
case India
case America
case Africa
case Australia
}
var season = Climate.America
season = .America
switch season {
case .India:
print("Climate is Hot")
case .America:
print("Climate is Cold")
case .Africa:
print("Climate is Moderate")
case .Australia:
print("Climate is Rainy")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Climate is Cold
Đầu tiên, chương trình định nghĩa Khí hậu là tên kiểu liệt kê. Sau đó, các thành viên của nó như 'Ấn Độ', 'Châu Mỹ', 'Châu Phi' và 'Úc' được tuyên bố là thuộc lớp 'Khí hậu'. Giờ đây, thành viên America được chỉ định vào một Season Variable. Hơn nữa, trường hợp Switch sẽ thấy các giá trị tương ứng với .America và nó sẽ phân nhánh cho câu lệnh cụ thể đó. Đầu ra sẽ được hiển thị là "Khí hậu lạnh". Tương tự như vậy, tất cả các thành viên có thể được truy cập thông qua các câu lệnh chuyển đổi. Khi điều kiện không được thỏa mãn, nó sẽ in theo mặc định "Không thể đoán trước được khí hậu".
Việc liệt kê có thể được phân loại thêm thành các giá trị liên quan và giá trị thô.
Sự khác biệt giữa Giá trị liên kết và Giá trị thô
Giá trị liên kết | Giá trị thô |
Các kiểu dữ liệu khác nhau | Cùng kiểu dữ liệu |
Ví dụ: enum {10,0.8, "Xin chào"} | Ví dụ: enum {10,35,50} |
Giá trị được tạo dựa trên hằng số hoặc biến | Giá trị phổ biến trước |
Thay đổi khi khai báo mỗi lần | Giá trị cho thành viên là như nhau |
Enum với các giá trị được liên kết
enum Student {
case Name(String)
case Mark(Int,Int,Int)
}
var studDetails = Student.Name("Swift 4")
var studMarks = Student.Mark(98,97,95)
switch studMarks {
case .Name(let studName):
print("Student name is: \(studName).")
case .Mark(let Mark1, let Mark2, let Mark3):
print("Student Marks are: \(Mark1),\(Mark2),\(Mark3).")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Student Marks are: 98,97,95.
Hãy xem xét ví dụ để truy cập tên sinh viên và các dấu được bảo mật trong ba môn học, tên liệt kê được khai báo là sinh viên và các thành viên có mặt trong lớp enum là tên thuộc kiểu dữ liệu chuỗi, các dấu được biểu diễn dưới dạng mark1, mark2 và mark3 của kiểu dữ liệu Integer. Để truy cập vào tên học sinh hoặc điểm họ đã ghi
var studDetails = Student.Name("Swift")
var studMarks = Student.Mark(98,97,95)
Bây giờ, trường hợp chuyển đổi sẽ in tên học sinh nếu khối trường hợp đó được thực thi nếu không, nó sẽ in các dấu được bảo mật bởi học sinh. Nếu cả hai điều kiện không thành công, khối mặc định sẽ được thực thi.
Enum với giá trị thô
Giá trị thô có thể là chuỗi, ký tự hoặc bất kỳ kiểu số nguyên hoặc 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ó. Khi số nguyên được sử dụng cho các giá trị thô, chúng sẽ tự động tăng lên nếu không có giá trị nào được chỉ định cho một số thành viên liệt kê.
enum Month: Int {
case January = 1, February, March, April, May, June, July, August,
September, October, November, December
}
let yearMonth = Month.May.rawValue
print("Value of the Month is: \(yearMonth).")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Value of the Month is: 5.
Swift 4 cung cấp một khối xây dựng linh hoạt sử dụng các cấu trúc làm Cấu trúc. Bằng cách sử dụng các cấu trúc này một lần có thể xác định các phương thức và thuộc tính cấu trúc.
Không giống như C và Mục tiêu C
Cấu trúc không cần thiết phải có tệp thực thi và giao diện.
Cấu trúc cho phép chúng ta tạo một tệp duy nhất và tự động mở rộng giao diện của nó sang các khối khác.
Trong Cấu trúc, các giá trị biến được sao chép và chuyển trong các mã tiếp theo bằng cách trả về một bản sao của các giá trị cũ để các giá trị không thể bị thay đổi.
Cú pháp
Structures are defined with a 'Struct' Keyword.
struct nameStruct {
Definition 1
Definition 2
---
Definition N
}
Định nghĩa cấu trúc
Hãy xem xét ví dụ, giả sử chúng ta phải truy cập hồ sơ học sinh có chứa điểm của ba môn học và để tìm ra tổng số ba môn học. Ở đây markStruct được sử dụng để khởi tạo một cấu trúc có ba dấu là kiểu dữ liệu 'Int'.
struct MarkStruct {
var mark1: Int
var mark2: Int
var mark3: Int
}
Truy cập cấu trúc và các thuộc tính của nó
Các thành viên của cấu trúc được truy cập bằng tên cấu trúc của nó. Các phiên bản của cấu trúc được khởi tạo bằng từ khóa 'let'.
struct studentMarks {
var mark1 = 100
var mark2 = 200
var mark3 = 300
}
let marks = studentMarks()
print("Mark1 is \(marks.mark1)")
print("Mark2 is \(marks.mark2)")
print("Mark3 is \(marks.mark3)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Mark1 is 100
Mark2 is 200
Mark3 is 300
Các điểm của sinh viên được truy cập bằng tên cấu trúc 'studentMarks'. Các thành viên cấu trúc được khởi tạo là mark1, mark2, mark3 với các giá trị kiểu số nguyên. Sau đó, cấu trúc studentMarks () được chuyển đến 'mark' với từ khóa 'let'. Sau đây 'dấu' sẽ chứa các giá trị thành viên cấu trúc. Bây giờ các giá trị được in ra bằng cách truy cập các giá trị thành viên cấu trúc bằng '.' với các tên đã khởi tạo của nó.
struct MarksStruct {
var mark: Int
init(mark: Int) {
self.mark = mark
}
}
var aStruct = MarksStruct(mark: 98)
var bStruct = aStruct // aStruct and bStruct are two structs with the same value!
bStruct.mark = 97
print(aStruct.mark) // 98
print(bStruct.mark) // 97
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
98
97
Các phương pháp sử dụng tốt nhất của cấu trúc
Ngôn ngữ Swift 4 cung cấp chức năng xác định cấu trúc như kiểu dữ liệu tùy chỉnh để xây dựng các khối chức năng. Các thể hiện của cấu trúc được chuyển theo giá trị của nó tới các khối được xác định để thực hiện các thao tác tiếp theo.
Cần có cấu trúc
Để đóng gói các giá trị dữ liệu đơn giản.
Để sao chép dữ liệu được đóng gói và các thuộc tính liên quan của nó bằng 'giá trị' thay vì 'tham chiếu'.
Cấu trúc thành 'Sao chép' và 'Tham chiếu'.
Các cấu trúc trong Swift 4 truyền cho các thành viên của chúng các giá trị của chúng chứ không phải bằng các tham chiếu của nó.
struct markStruct {
var mark1: Int
var mark2: Int
var mark3: Int
init(mark1: Int, mark2: Int, mark3: Int) {
self.mark1 = mark1
self.mark2 = mark2
self.mark3 = mark3
}
}
var marks = markStruct(mark1: 98, mark2: 96, mark3:100)
print(marks.mark1)
print(marks.mark2)
print(marks.mark3)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
98
96
100
Một vi dụ khac
struct markStruct {
var mark1: Int
var mark2: Int
var mark3: Int
init(mark1: Int, mark2: Int, mark3: Int) {
self.mark1 = mark1
self.mark2 = mark2
self.mark3 = mark3
}
}
var fail = markStruct(mark1: 34, mark2: 42, mark3: 13)
print(fail.mark1)
print(fail.mark2)
print(fail.mark3)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
34
42
13
Cấu trúc 'markStruct' được xác định đầu tiên với các thành viên của nó là mark1, mark2 và mark3. Bây giờ các biến của các lớp thành viên được khởi tạo để giữ các giá trị nguyên. Sau đó, bản sao của các thành viên cấu trúc được tạo bằng Từ khóa 'tự'. Khi bản sao của các thành viên cấu trúc được tạo ra, khối cấu trúc với các dấu tham số của nó sẽ được chuyển đến biến 'mark', biến này sẽ giữ các điểm của sinh viên. Sau đó, các dấu được in là 98, 96, 100. Bước tiếp theo đối với các thành viên cấu trúc giống nhau, một thể hiện khác có tên 'fail' được sử dụng để trỏ các thành viên cấu trúc giống nhau với các dấu khác nhau. Sau đó, kết quả bây giờ được in ra dưới dạng 34, 42, 13. Điều này giải thích rõ ràng rằng các cấu trúc sẽ có một bản sao của các biến thành viên sau đó chuyển các thành viên đến các khối chức năng sắp tới của chúng.
Các lớp trong Swift 4 là khối xây dựng các cấu trúc linh hoạt. Tương tự với hằng, biến và hàm, người dùng có thể xác định các thuộc tính và phương thức của lớp. Swift 4 cung cấp cho chúng ta chức năng mà trong khi khai báo các lớp, người dùng không cần tạo giao diện hoặc tệp thực thi. Swift 4 cho phép chúng ta tạo các lớp dưới dạng một tệp duy nhất và các giao diện bên ngoài sẽ được tạo theo mặc định sau khi các lớp được khởi tạo.
Lợi ích của việc có Lớp học
Kế thừa có được các thuộc tính của một lớp này sang một lớp khác
Truyền kiểu cho phép người dùng kiểm tra loại lớp tại thời gian chạy
Deinitializers chăm sóc giải phóng tài nguyên bộ nhớ
Việc đếm tham chiếu cho phép cá thể lớp có nhiều hơn một tham chiếu
Đặc điểm chung của các lớp và cấu trúc
- Thuộc tính được xác định để lưu trữ các giá trị
- Các đăng ký được xác định để cung cấp quyền truy cập vào các giá trị
- Các phương thức được khởi tạo để cải thiện chức năng
- Trạng thái ban đầu được xác định bởi trình khởi tạo
- Chức năng được mở rộng ra ngoài các giá trị mặc định
- Xác nhận các tiêu chuẩn chức năng của giao thức
Cú pháp
Class classname {
Definition 1
Definition 2
---
Definition N
}
Định nghĩa lớp
class student {
var studname: String
var mark: Int
var mark2: Int
}
Cú pháp để tạo phiên bản
let studrecord = student()
Thí dụ
class MarksStruct {
var mark: Int
init(mark: Int) {
self.mark = mark
}
}
class studentMarks {
var mark = 300
}
let marks = studentMarks()
print("Mark is \(marks.mark)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Mark is 300
Truy cập thuộc tính lớp dưới dạng tham chiếu
Các thuộc tính của lớp có thể được truy cập bằng dấu '.' cú pháp. Tên thuộc tính được phân tách bằng dấu '.' sau tên cá thể.
class MarksStruct {
var mark: Int
init(mark: Int) {
self.mark = mark
}
}
class studentMarks {
var mark1 = 300
var mark2 = 400
var mark3 = 900
}
let marks = studentMarks()
print("Mark1 is \(marks.mark1)")
print("Mark2 is \(marks.mark2)")
print("Mark3 is \(marks.mark3)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Mark1 is 300
Mark2 is 400
Mark3 is 900
Toán tử Nhận dạng Lớp
Các lớp trong Swift 4 đề cập đến nhiều hằng số và biến trỏ đến một trường hợp duy nhất. Để biết về các hằng số và biến trỏ đến một cá thể lớp cụ thể, các toán tử nhận dạng được sử dụng. Các cá thể của lớp luôn được chuyển qua tham chiếu. Trong các lớp, các thể hiện NSString, NSArray và NSDictionary luôn được gán và chuyển xung quanh như một tham chiếu đến một cá thể hiện có, chứ không phải là một bản sao.
Giống hệt nhà điều hành | Không giống hệt nhà điều hành |
---|---|
Toán tử được sử dụng là (===) | Toán tử được sử dụng là (! ==) |
Trả về true khi hai hằng hoặc biến trỏ đến cùng một trường hợp | Trả về true khi hai hằng số hoặc biến trỏ đến một phiên bản khác |
class SampleClass: Equatable {
let myProperty: String
init(s: String) {
myProperty = s
}
}
func ==(lhs: SampleClass, rhs: SampleClass) -> Bool {
return lhs.myProperty == rhs.myProperty
}
let spClass1 = SampleClass(s: "Hello")
let spClass2 = SampleClass(s: "Hello")
spClass1 === spClass2 // false
print("\(spClass1)")
spClass1 !== spClass2 // true
print("\(spClass2)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
main.SampleClass
main.SampleClass
Ngôn ngữ Swift 4 cung cấp các thuộc tính cho lớp, kiểu liệt kê hoặc cấu trúc để liên kết các giá trị. Thuộc tính có thể được phân loại thêm thành thuộc tính được lưu trữ và thuộc tính được tính toán.
Sự khác biệt giữa Thuộc tính được lưu trữ và Thuộc tính được tính
Tài sản lưu trữ | Thuộc tính tính toán |
---|---|
Lưu trữ các giá trị hằng và biến dưới dạng phiên bản | Tính toán giá trị thay vì lưu trữ giá trị |
Được cung cấp bởi các lớp và cấu trúc | Được cung cấp bởi các lớp, kiểu liệt kê và cấu trúc |
Cả hai thuộc tính được lưu trữ và tính toán đều được liên kết với loại phiên bản. Khi các thuộc tính được liên kết với các giá trị kiểu của nó thì nó được định nghĩa là 'Thuộc tính kiểu'. Các thuộc tính được lưu trữ và tính toán thường được liên kết với các phiên bản của một loại cụ thể. Tuy nhiên, các thuộc tính cũng có thể được liên kết với chính kiểu đó. Thuộc tính như vậy được gọi là thuộc tính kiểu. Người quan sát tài sản cũng được sử dụng
- Để quan sát giá trị của các thuộc tính được lưu trữ
- Để quan sát thuộc tính của lớp con kế thừa có nguồn gốc từ lớp cha
Thuộc tính được lưu trữ
Swift 4 giới thiệu khái niệm Thuộc tính lưu trữ để lưu trữ các thể hiện của hằng và biến. Các thuộc tính được lưu trữ của các hằng số được xác định bởi từ khóa 'let' và các thuộc tính được lưu trữ của các biến được xác định bởi từ khóa 'var'.
- Trong định nghĩa Thuộc tính được lưu trữ cung cấp 'giá trị mặc định'
- Trong quá trình khởi tạo, người dùng có thể khởi tạo và sửa đổi các giá trị ban đầu
struct Number {
var digits: Int
let pi = 3.1415
}
var n = Number(digits: 12345)
n.digits = 67
print("\(n.digits)")
print("\(n.pi)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
67
3.1415
Hãy xem xét dòng sau trong đoạn mã trên:
let pi = 3.1415
Ở đây, biến pi được khởi tạo như một giá trị thuộc tính được lưu trữ với ví dụ pi = 3,1415. Vì vậy, bất cứ khi nào cá thể được tham chiếu, nó sẽ giữ giá trị 3,1415 một mình.
Một phương pháp khác để có thuộc tính được lưu trữ là có các cấu trúc không đổi. Vì vậy, toàn bộ thể hiện của cấu trúc sẽ được coi là 'Thuộc tính được lưu trữ của hằng số'.
struct Number {
var digits: Int
let numbers = 3.1415
}
var n = Number(digits: 12345)
n.digits = 67
print("\(n.digits)")
print("\(n.numbers)")
n.numbers = 8.7
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
error: cannot assign to 'numbers' in 'n'
n.numbers = 8.7
Thay vì khởi động lại 'số' thành 8.7, nó sẽ trả về thông báo lỗi cho biết 'số' được khai báo là hằng số.
Tài sản được lưu trữ lười biếng
Swift 4 cung cấp một thuộc tính linh hoạt được gọi là 'Lazy Stored Property', nơi nó sẽ không tính toán các giá trị ban đầu khi biến được khởi tạo lần đầu tiên. sửa đổi 'lazy' được sử dụng trước khai báo biến để có nó như một thuộc tính lưu trữ lười biếng.
Thuộc tính Lazy được sử dụng -
- Để trì hoãn việc tạo đối tượng.
- Khi thuộc tính phụ thuộc vào các phần khác của một lớp, điều đó chưa được biết đến
class sample {
lazy var no = number() // `var` declaration is required.
}
class number {
var name = "Swift 4"
}
var firstsample = sample()
print(firstsample.no.name)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Swift 4
Biến thể hiện
Trong Objective C, thuộc tính Stored cũng có các biến thể hiện cho mục đích sao lưu để lưu trữ các giá trị được khai báo trong thuộc tính được lưu trữ.
Swift 4 tích hợp cả hai khái niệm này vào một khai báo 'thuộc tính được lưu trữ' duy nhất. Thay vì có một biến phiên bản tương ứng và giá trị sao lưu 'thuộc tính được lưu trữ' chứa tất cả thông tin tích hợp được xác định ở một vị trí duy nhất về thuộc tính biến theo tên biến, kiểu dữ liệu và chức năng quản lý bộ nhớ.
Thuộc tính tính toán
Thay vì lưu trữ các giá trị, các thuộc tính đã tính toán cung cấp một getter và một setter tùy chọn để truy xuất và đặt các thuộc tính và giá trị khác một cách gián tiếp.
class sample {
var no1 = 0.0, no2 = 0.0
var length = 300.0, breadth = 150.0
var middle: (Double, Double) {
get {
return (length / 2, breadth / 2)
}
set(axis){
no1 = axis.0 - (length / 2)
no2 = axis.1 - (breadth / 2)
}
}
}
var result = sample()
print(result.middle)
result.middle = (0.0, 10.0)
print(result.no1)
print(result.no2)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
(150.0, 75.0)
-150.0
-65.0
Khi một thuộc tính được tính toán để lại giá trị mới là không xác định, giá trị mặc định sẽ được đặt cho biến cụ thể đó.
Thuộc tính được tính toán dưới dạng thuộc tính chỉ đọc
Thuộc tính chỉ đọc trong thuộc tính được tính toán được định nghĩa là thuộc tính có getter nhưng không có setter. Nó luôn được sử dụng để trả về một giá trị. Các biến được truy cập thêm thông qua dấu '.' Cú pháp nhưng không thể được đặt thành giá trị khác.
class film {
var head = ""
var duration = 0.0
var metaInfo: [String:String] {
return [
"head": self.head,
"duration":"\(self.duration)"
]
}
}
var movie = film()
movie.head = "Swift 4 Properties"
movie.duration = 3.09
print(movie.metaInfo["head"]!)
print(movie.metaInfo["duration"]!)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Swift 4 Properties
3.09
Thuộc tính được tính toán với tư cách là người quan sát thuộc tính
Trong Swift 4 để quan sát và phản hồi các giá trị thuộc tính, Trình quan sát tài sản được sử dụng. Mỗi và mọi lúc khi các giá trị thuộc tính được thiết lập, các trình quan sát thuộc tính được gọi. Ngoại trừ các thuộc tính được lưu trữ lười biếng, chúng ta có thể thêm các trình quan sát thuộc tính vào thuộc tính 'kế thừa' bằng phương pháp 'ghi đè'.
Người quan sát thuộc tính có thể được xác định bởi
Trước khi lưu trữ giá trị - willset
Sau khi lưu trữ giá trị mới - didset
Khi một thuộc tính được đặt trong bộ khởi tạo sẽ thiết lập và không thể gọi các quan sát viên didset.
class Samplepgm {
var counter: Int = 0 {
willSet(newTotal){
print("Total Counter is: \(newTotal)")
}
didSet {
if counter > oldValue {
print("Newly Added Counter \(counter - oldValue)")
}
}
}
}
let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700
Biến cục bộ và toàn cục
Biến cục bộ và toàn cục được khai báo để tính toán và quan sát các thuộc tính.
Biến cục bộ | Biến toàn cục |
---|---|
Các biến được xác định trong một hàm, phương thức hoặc ngữ cảnh đóng. | Các biến được xác định bên ngoài ngữ cảnh hàm, phương thức, bao đóng hoặc kiểu. |
Được sử dụng để lưu trữ và truy xuất các giá trị. | Được sử dụng để lưu trữ và truy xuất các giá trị. |
Thuộc tính được lưu trữ được sử dụng để lấy và đặt các giá trị. | Thuộc tính được lưu trữ được sử dụng để lấy và đặt các giá trị. |
Thuộc tính tính toán cũng được sử dụng. | Thuộc tính tính toán cũng được sử dụng. |
Loại Thuộc tính
Các thuộc tính được định nghĩa trong phần Định nghĩa kiểu với dấu ngoặc nhọn {} và phạm vi của các biến cũng đã được xác định trước đó. Để xác định thuộc tính kiểu cho các kiểu giá trị, từ khóa 'static' được sử dụng và từ khóa 'class' được sử dụng cho các loại lớp.
Cú pháp
struct Structname {
static var storedTypeProperty = " "
static var computedTypeProperty: Int {
// return an Int value here
}
}
enum Enumname {
static var storedTypeProperty = " "
static var computedTypeProperty: Int {
// return an Int value here
}
}
class Classname {
class var computedTypeProperty: Int {
// return an Int value here
}
}
Truy vấn và thiết lập thuộc tính
Cũng giống như các thuộc tính instance Thuộc tính loại được truy vấn và đặt bằng '.' Cú pháp chỉ trên loại thay vì trỏ đến cá thể.
struct StudMarks {
static let markCount = 97
static var totalCount = 0
var InternalMarks: Int = 0 {
didSet {
if InternalMarks > StudMarks.markCount {
InternalMarks = StudMarks.markCount
}
if InternalMarks > StudMarks.totalCount {
StudMarks.totalCount = InternalMarks
}
}
}
}
var stud1Mark1 = StudMarks()
var stud1Mark2 = StudMarks()
stud1Mark1.InternalMarks = 98
print(stud1Mark1.InternalMarks)
stud1Mark2.InternalMarks = 87
print(stud1Mark2.InternalMarks)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
97
87
Trong ngôn ngữ Swift 4, các hàm được liên kết với các kiểu cụ thể được gọi là Phương thức. Trong Objective C, các lớp được sử dụng để định nghĩa các phương thức, trong khi ngôn ngữ Swift 4 cung cấp cho người dùng sự linh hoạt để có các phương thức cho Lớp, Cấu trúc và Danh sách.
Phương pháp phiên bản
Trong ngôn ngữ Swift 4, các cá thể Lớp, Cấu trúc và Liệt kê được truy cập thông qua các phương thức cá thể.
Phương thức phiên bản cung cấp chức năng
- Để truy cập và sửa đổi thuộc tính phiên bản
- chức năng liên quan đến nhu cầu của phiên bản
Phương thức thể hiện có thể được viết bên trong dấu ngoặc nhọn {}. Nó có quyền truy cập ngầm vào các phương thức và thuộc tính của thể hiện kiểu. Khi một thể hiện cụ thể của kiểu được gọi, nó sẽ có quyền truy cập vào thể hiện cụ thể đó.
Cú pháp
func funcname(Parameters) -> returntype {
Statement1
Statement2
---
Statement N
return parameters
}
Thí dụ
class calculations {
let a: Int
let b: Int
let res: Int
init(a: Int, b: Int) {
self.a = a
self.b = b
res = a + b
}
func tot(c: Int) -> Int {
return res - c
}
func result() {
print("Result is: \(tot(c: 20))")
print("Result is: \(tot(c: 50))")
}
}
let pri = calculations(a: 600, b: 300)
pri.result()
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Result is: 880
Result is: 850
Tính toán lớp xác định hai phương thức thể hiện:
- init () được định nghĩa để thêm hai số a và b và lưu trữ nó trong kết quả 'res'
- tot () được dùng để trừ giá trị 'res' chuyển sang giá trị 'c'
Cuối cùng, để in ra các phương thức tính toán với các giá trị cho a và b được gọi. Các phương thức phiên bản được truy cập bằng '.' cú pháp dấu chấm
Tên tham số cục bộ và bên ngoài
Các hàm Swift 4 mô tả cả khai báo cục bộ và toàn cục cho các biến của chúng. Tương tự, các quy ước đặt tên của Swift 4 Method cũng giống như của Objective C. Nhưng các đặc điểm của khai báo tên tham số cục bộ và toàn cục là khác nhau đối với các hàm và phương thức. Tham số đầu tiên trong Swift 4 được gọi bằng các tên giới từ như 'with', 'for' và 'by' để dễ dàng truy cập các quy ước đặt tên.
Swift 4 cung cấp sự linh hoạt trong các phương thức bằng cách khai báo tên tham số đầu tiên là tên tham số cục bộ và các tên tham số còn lại là tên tham số toàn cục. Ở đây 'no1' được khai báo bởi các phương thức Swift 4 dưới dạng tên tham số cục bộ. 'no2' được sử dụng cho các khai báo toàn cục và được truy cập thông qua chương trình.
class division {
var count: Int = 0
func incrementBy(no1: Int, no2: Int) {
count = no1 / no2
print(count)
}
}
let counter = division()
counter.incrementBy(no1: 1800, no2: 3)
counter.incrementBy(no1: 1600, no2: 5)
counter.incrementBy(no1: 11000, no2: 3)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
600
320
3666
Tên thông số bên ngoài với ký hiệu # và _
Mặc dù các phương thức Swift 4 cung cấp tên tham số đầu tiên cho các khai báo cục bộ, người dùng có điều kiện sửa đổi tên tham số từ khai báo cục bộ thành toàn cục. Điều này có thể được thực hiện bằng cách thêm tiền tố '#' vào tên tham số đầu tiên. Bằng cách đó, tham số đầu tiên có thể được truy cập trên toàn cầu trong suốt các mô-đun.
Khi người dùng cần truy cập các tên tham số tiếp theo với tên bên ngoài, tên phương thức sẽ được ghi đè với sự trợ giúp của ký hiệu '_'.
class multiplication {
var count: Int = 0
func incrementBy(no1: Int, no2: Int) {
count = no1 * no2
print(count)
}
}
let counter = multiplication()
counter.incrementBy(no1: 800, no2: 3)
counter.incrementBy(no1: 100, no2: 5)
counter.incrementBy(no1: 15000, no2: 3)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
2400
500
45000
Thuộc tính bản thân trong các phương thức
Các phương thức có một thuộc tính ngầm được gọi là 'self' cho tất cả các trường hợp kiểu được xác định của nó. Thuộc tính 'self' được sử dụng để tham chiếu các trường hợp hiện tại cho các phương thức được xác định của nó.
class calculations {
let a: Int
let b: Int
let res: Int
init(a: Int, b: Int) {
self.a = a
self.b = b
res = a + b
print("Inside Self Block: \(res)")
}
func tot(c: Int) -> Int {
return res - c
}
func result() {
print("Result is: \(tot(c: 20))")
print("Result is: \(tot(c: 50))")
}
}
let pri = calculations(a: 600, b: 300)
let sum = calculations(a: 1200, b: 300)
pri.result()
sum.result()
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Inside Self Block: 900
Inside Self Block: 1500
Result is: 880
Result is: 850
Result is: 1480
Result is: 1450
Sửa đổi các loại giá trị từ các phương thức phiên bản
Trong ngôn ngữ Swift 4, cấu trúc và bảng liệt kê thuộc về các kiểu giá trị không thể thay đổi bằng các phương thức thể hiện của nó. Tuy nhiên, ngôn ngữ Swift 4 cung cấp sự linh hoạt để sửa đổi các loại giá trị bằng cách 'biến đổi' hành vi. Mutate sẽ thực hiện bất kỳ thay đổi nào trong các phương thức thể hiện và sẽ trở lại dạng ban đầu sau khi thực thi phương thức. Ngoài ra, bởi thuộc tính 'self', trường hợp mới được tạo cho chức năng ngầm định của nó và sẽ thay thế phương thức hiện có sau khi thực thi
struct area {
var length = 1
var breadth = 1
func area() -> Int {
return length * breadth
}
mutating func scaleBy(res: Int) {
length *= res
breadth *= res
print(length)
print(breadth)
}
}
var val = area(length: 3, breadth: 5)
val.scaleBy(res: 3)
val.scaleBy(res: 30)
val.scaleBy(res: 300)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
9
15
270
450
81000
135000
Tài sản tự có cho phương pháp đột biến
Các phương thức thay đổi kết hợp với thuộc tính 'self' sẽ gán một phiên bản mới cho phương thức đã xác định.
struct area {
var length = 1
var breadth = 1
func area() -> Int {
return length * breadth
}
mutating func scaleBy(res: Int) {
self.length *= res
self.breadth *= res
print(length)
print(breadth)
}
}
var val = area(length: 3, breadth: 5)
val.scaleBy(res: 13)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau. -
39
65
Loại phương pháp
Khi một thể hiện cụ thể của một phương thức được gọi, nó được gọi là một phương thức Instance; và khi phương thức gọi một kiểu cụ thể của một phương thức, nó được gọi là 'Phương thức kiểu'. Phương thức loại cho 'các lớp' được xác định bởi từ khóa 'func' và các cấu trúc và phương thức kiểu liệt kê được xác định với từ khóa 'tĩnh' trước từ khóa 'func'.
Các phương thức kiểu được gọi và truy cập bởi '.' cú pháp trong đó thay vì gọi một trường hợp cụ thể, toàn bộ phương thức được gọi.
class Math {
class func abs(number: Int) -> Int {
if number < 0 {
return (-number)
} else {
return number
}
}
}
struct absno {
static func abs(number: Int) -> Int {
if number < 0 {
return (-number)
} else {
return number
}
}
}
let no = Math.abs(number: -35)
let num = absno.abs(number: -5)
print(no)
print(num)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau. -
35
5
Việc truy cập các thành viên phần tử của một tập hợp, trình tự và danh sách trong Lớp, Cấu trúc và Kiểu liệt kê được thực hiện với sự trợ giúp của các chỉ số con. Các chỉ số con này được sử dụng để lưu trữ và truy xuất các giá trị với sự trợ giúp của chỉ mục. Các phần tử của mảng được truy cập với sự trợ giúp của someArray [chỉ mục] và các phần tử thành viên tiếp theo của nó trong một cá thể Từ điển có thể được truy cập dưới dạng someDicitionary [key].
Đối với một loại duy nhất, các chỉ số con có thể từ một đến nhiều khai báo. Chúng ta có thể sử dụng chỉ số con thích hợp để nạp chồng loại giá trị chỉ mục được truyền vào chỉ số con. Các chỉ số cũng có phạm vi từ một thứ nguyên đến nhiều thứ nguyên tùy theo yêu cầu của người dùng đối với khai báo kiểu dữ liệu đầu vào của họ.
Cú pháp khai báo chỉ số con và cách sử dụng nó
Hãy tóm tắt lại các thuộc tính được tính toán. Các đăng ký cũng tuân theo cùng một cú pháp như của các thuộc tính được tính toán. Đối với phiên bản kiểu truy vấn, các chỉ số con được viết bên trong một dấu ngoặc vuông theo sau với tên phiên bản. Cú pháp chỉ số phụ tuân theo cấu trúc cú pháp tương tự như cú pháp của 'phương thức phiên bản' và 'thuộc tính được tính toán'. Từ khóa 'subscript' được sử dụng để xác định chỉ số phụ và người dùng có thể chỉ định một hoặc nhiều tham số với kiểu trả về của chúng. Các chỉ số con có thể có các thuộc tính đọc-ghi hoặc chỉ đọc và các thể hiện được lưu trữ và truy xuất với sự trợ giúp của các thuộc tính 'getter' và 'setter' giống như các thuộc tính được tính toán.
Cú pháp
subscript(index: Int) −> Int {
get {
// used for subscript value declarations
}
set(newValue) {
// definitions are written here
}
}
Ví dụ 1
struct subexample {
let decrementer: Int
subscript(index: Int) -> Int {
return decrementer / index
}
}
let division = subexample(decrementer: 100)
print("The number is divisible by \(division[9]) times")
print("The number is divisible by \(division[2]) times")
print("The number is divisible by \(division[3]) times")
print("The number is divisible by \(division[5]) times")
print("The number is divisible by \(division[7]) times")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
The number is divisible by 11 times
The number is divisible by 50 times
The number is divisible by 33 times
The number is divisible by 20 times
The number is divisible by 14 times
Ví dụ2
class daysofaweek {
private var days = ["Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "saturday"]
subscript(index: Int) -> String {
get {
return days[index]
}
set(newValue) {
self.days[index] = newValue
}
}
}
var p = daysofaweek()
print(p[0])
print(p[1])
print(p[2])
print(p[3])
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Sunday
Monday
Tuesday
Wednesday
Tùy chọn trong Chỉ số
Các chỉ số đăng ký nhận đơn lẻ đến nhiều tham số đầu vào và các tham số đầu vào này cũng thuộc về bất kỳ kiểu dữ liệu nào. Họ cũng có thể sử dụng các tham số biến và đa dạng. Các đăng ký không thể cung cấp các giá trị tham số mặc định hoặc sử dụng bất kỳ tham số đầu vào nào.
Định nghĩa nhiều chỉ số con được gọi là 'nạp chồng chỉ số con' trong đó một lớp hoặc cấu trúc có thể cung cấp nhiều định nghĩa chỉ số con theo yêu cầu. Nhiều chỉ số con này được suy ra dựa trên các loại giá trị được khai báo trong dấu ngoặc nhọn chỉ số con.
struct Matrix {
let rows: Int, columns: Int
var print: [Double]
init(rows: Int, columns: Int) {
self.rows = rows
self.columns = columns
print = Array(count: rows * columns, repeatedValue: 0.0)
}
subscript(row: Int, column: Int) -> Double {
get {
return print[(row * columns) + column]
}
set {
print[(row * columns) + column] = newValue
}
}
}
var mat = Matrix(rows: 3, columns: 3)
mat[0,0] = 1.0
mat[0,1] = 2.0
mat[1,0] = 3.0
mat[1,1] = 5.0
print("\(mat[0,0])")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
1.0
Swift 4 subscript hỗ trợ một tham số cho nhiều khai báo tham số cho các kiểu dữ liệu thích hợp. Chương trình khai báo cấu trúc 'Matrix' là ma trận mảng 2 * 2 chiều để lưu các kiểu dữ liệu 'Double'. Tham số Ma trận được nhập với kiểu dữ liệu Số nguyên để khai báo hàng và cột.
Thể hiện mới cho Ma trận được tạo bằng cách chuyển số hàng và số cột vào lần khởi tạo như hình dưới đây.
var mat = Matrix(rows: 3, columns: 3)
Giá trị ma trận có thể được xác định bằng cách chuyển các giá trị hàng và cột vào chỉ số con, được phân tách bằng dấu phẩy như hình dưới đây.
mat[0,0] = 1.0
mat[0,1] = 2.0
mat[1,0] = 3.0
mat[1,1] = 5.0
Khả năng có nhiều dạng hơn được định nghĩa là Thừa kế. Nói chung một lớp có thể kế thừa các phương thức, thuộc tính và chức năng từ một lớp khác. Các lớp có thể được phân loại thêm thành lớp con và lớp siêu.
Sub Class - khi một lớp kế thừa các thuộc tính, phương thức và hàm từ một lớp khác thì nó được gọi là lớp con
Super Class - Lớp chứa các thuộc tính, phương thức và hàm để kế thừa các lớp khác từ chính nó được gọi là siêu lớp
Các lớp Swift 4 chứa lớp cha gọi và truy cập các phương thức, thuộc tính, hàm và phương thức ghi đè. Ngoài ra, các trình quan sát thuộc tính cũng được sử dụng để thêm thuộc tính và sửa đổi các phương thức thuộc tính được lưu trữ hoặc tính toán.
Lớp cơ sở
Một Lớp không kế thừa các phương thức, thuộc tính hoặc chức năng từ một lớp khác được gọi là 'Lớp Cơ sở'.
class StudDetails {
var stname: String!
var mark1: Int!
var mark2: Int!
var mark3: Int!
init(stname: String, mark1: Int, mark2: Int, mark3: Int) {
self.stname = stname
self.mark1 = mark1
self.mark2 = mark2
self.mark3 = mark3
}
}
let stname = "Swift 4"
let mark1 = 98
let mark2 = 89
let mark3 = 76
print(stname)
print(mark1)
print(mark2)
print(mark3)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Swift 4
98
89
76
Lớp có tên lớp là StudDetails được định nghĩa là lớp cơ sở ở đây được sử dụng để chứa tên sinh viên và ba môn học được đánh dấu là mark1, mark2 và mark3. Từ khóa 'let' được sử dụng để khởi tạo giá trị cho lớp cơ sở và giá trị lớp cơ sở được hiển thị trong sân chơi với sự trợ giúp của hàm 'print'.
Lớp con
Hành động dựa trên một lớp mới trên một lớp hiện có được định nghĩa là 'Lớp con'. Lớp con kế thừa các thuộc tính, phương thức và chức năng của lớp cơ sở của nó. Để định nghĩa một lớp con ':' được sử dụng trước tên lớp cơ sở
class StudDetails {
var mark1: Int;
var mark2: Int;
init(stm1:Int, results stm2:Int) {
mark1 = stm1;
mark2 = stm2;
}
func print() {
print("Mark1:\(mark1), Mark2:\(mark2)")
}
}
class display : StudDetails {
init() {
super.init(stm1: 93, results: 89)
}
}
let marksobtained = display()
marksobtained.print()
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Mark1:93, Mark2:89
Lớp 'StudDetails' được định nghĩa là siêu lớp nơi khai báo điểm của sinh viên và lớp con 'display' được sử dụng để kế thừa các dấu từ siêu lớp của nó. Lớp con xác định dấu của sinh viên và gọi phương thức print () để hiển thị dấu sinh viên.
Ghi đè
Việc truy cập cá thể siêu lớp, các phương thức kiểu, cá thể, thuộc tính kiểu và lớp con subscripts cung cấp khái niệm ghi đè. Từ khóa 'override' được sử dụng để ghi đè các phương thức được khai báo trong lớp cha.
Quyền truy cập vào các phương thức, thuộc tính và chỉ số siêu lớp
Từ khóa 'super' được sử dụng như một tiền tố để truy cập các phương thức, thuộc tính và chỉ số con được khai báo trong lớp siêu
Ghi đè | Quyền truy cập vào các phương thức, thuộc tính và chỉ số con |
Phương pháp | super.somemethod () |
Tính chất | super.someProperty () |
Đăng ký | siêu [someIndex] |
Ghi đè phương thức
Các phương thức kiểu và trường hợp kế thừa có thể bị từ khóa 'override' ghi đè lên các phương thức được định nghĩa trong lớp con của chúng ta. Ở đây print () được ghi đè trong lớp con để truy cập thuộc tính kiểu được đề cập trong siêu lớp print (). Ngoài ra, phiên bản mới của siêu lớp cricket () cũng được tạo ra dưới dạng 'cricinstance'.
class cricket {
func print() {
print("Welcome to Swift 4 Super Class")
}
}
class tennis: cricket {
override func print() {
print("Welcome to Swift 4 Sub Class")
}
}
let cricinstance = cricket()
cricinstance.print()
let tennisinstance = tennis()
tennisinstance.print()
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Welcome to Swift Super Class
Welcome to Swift Sub Class
Ghi đè tài sản
Bạn có thể ghi đè thuộc tính lớp hoặc phiên bản được kế thừa để cung cấp bộ thu và bộ cài đặt tùy chỉnh của riêng bạn cho thuộc tính đó hoặc thêm người quan sát thuộc tính để cho phép thuộc tính ghi đè quan sát khi giá trị thuộc tính cơ bản thay đổi.
Ghi đè người nhận và người định đoạt tài sản
Swift 4 cho phép người dùng cung cấp getter và setter tùy chỉnh để ghi đè lên thuộc tính kế thừa cho dù đó là thuộc tính được lưu trữ hay được tính toán. Lớp con không biết tên và kiểu thuộc tính kế thừa. Do đó, điều cần thiết là người dùng cần chỉ định trong lớp con, tên và kiểu của thuộc tính ghi đè được chỉ định trong lớp siêu.
Điều này có thể được thực hiện theo hai cách -
Khi setter được xác định để ghi đè thuộc tính, người dùng cũng phải xác định getter.
Khi chúng ta không muốn sửa đổi getter thuộc tính kế thừa, chúng ta có thể chỉ cần chuyển giá trị được kế thừa bằng cú pháp 'super.someProperty' cho lớp siêu.
class Circle {
var radius = 12.5
var area: String {
return "of rectangle for \(radius) "
}
}
class Rectangle: Circle {
var print = 7
override var area: String {
return super.area + " is now overridden as \(print)"
}
}
let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Radius of rectangle for 25.0 is now overridden as 3
Ghi đè người quan sát tài sản
Khi một thuộc tính mới cần được thêm vào cho một thuộc tính được kế thừa, khái niệm 'ghi đè thuộc tính' được giới thiệu trong Swift 4. Điều này thông báo cho người dùng khi giá trị thuộc tính được thừa kế bị thay đổi. Nhưng ghi đè không thể áp dụng cho các thuộc tính được lưu trữ không đổi được kế thừa và các thuộc tính được tính chỉ đọc được kế thừa.
class Circle {
var radius = 12.5
var area: String {
return "of rectangle for \(radius) "
}
}
class Rectangle: Circle {
var print = 7
override var area: String {
return super.area + " is now overridden as \(print)"
}
}
let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")
class Square: Rectangle {
override var radius: Double {
didSet {
print = Int(radius/5.0)+1
}
}
}
let sq = Square()
sq.radius = 100.0
print("Radius \(sq.area)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Radius of rectangle for 25.0 is now overridden as 3
Radius of rectangle for 100.0 is now overridden as 21
Thuộc tính cuối cùng để ngăn Ghi đè
Khi người dùng không muốn người khác truy cập vào các phương thức, thuộc tính hoặc chỉ số con của siêu lớp, Swift 4 giới thiệu thuộc tính 'cuối cùng' để ngăn ghi đè. Khi thuộc tính 'cuối cùng' được khai báo, các chỉ số con sẽ không cho phép ghi đè các phương thức, thuộc tính của lớp siêu cấp và các chỉ số con của nó. Không có quy định nào để có tài sản 'cuối cùng' trong 'siêu hạng'. Khi thuộc tính 'cuối cùng' được khai báo, người dùng bị hạn chế tạo thêm các lớp con.
final class Circle {
final var radius = 12.5
var area: String {
return "of rectangle for \(radius) "
}
}
class Rectangle: Circle {
var print = 7
override var area: String {
return super.area + " is now overridden as \(print)"
}
}
let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")
class Square: Rectangle {
override var radius: Double {
didSet {
print = Int(radius/5.0)+1
}
}
}
let sq = Square()
sq.radius = 100.0
print("Radius \(sq.area)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
<stdin>:14:18: error: var overrides a 'final' var
override var area: String {
^
<stdin>:7:9: note: overridden declaration is here
var area: String {
^
<stdin>:12:11: error: inheritance from a final class 'Circle'
class Rectangle: Circle {
^
<stdin>:25:14: error: var overrides a 'final' var
override var radius: Double {
^
<stdin>:6:14: note: overridden declaration is here
final var radius = 12.5
Vì siêu lớp được khai báo là 'cuối cùng' và các kiểu dữ liệu của nó cũng được khai báo là 'cuối cùng' nên chương trình sẽ không cho phép tạo thêm các lớp con và nó sẽ tạo ra lỗi.
Các lớp, cấu trúc và kiểu liệt kê từng được khai báo trong Swift 4 được khởi tạo để chuẩn bị thể hiện của một lớp. Giá trị ban đầu được khởi tạo cho thuộc tính được lưu trữ và cũng cho các trường hợp mới, các giá trị cũng được khởi tạo để tiếp tục. Từ khóa tạo hàm khởi tạo được thực hiện bằng phương thức 'init ()'. Bộ khởi tạo Swift 4 khác với Objective-C là nó không trả về bất kỳ giá trị nào. Chức năng của nó là kiểm tra việc khởi tạo các thể hiện mới được tạo trước khi xử lý. Swift 4 cũng cung cấp quy trình 'deinitialization' để thực hiện các hoạt động quản lý bộ nhớ sau khi các cá thể được phân bổ.
Vai trò khởi tạo cho các thuộc tính được lưu trữ
Thuộc tính lưu trữ phải khởi tạo các thể hiện cho các lớp và cấu trúc của nó trước khi xử lý các thể hiện. Các thuộc tính được lưu trữ sử dụng bộ khởi tạo để gán và khởi tạo các giá trị do đó loại bỏ nhu cầu gọi các trình quan sát thuộc tính. Bộ khởi tạo được sử dụng trong tài sản được lưu trữ
Để tạo một giá trị ban đầu.
Để gán giá trị thuộc tính mặc định trong định nghĩa thuộc tính.
Để khởi tạo một thể hiện cho một kiểu dữ liệu cụ thể 'init ()' được sử dụng. Không có đối số nào được truyền vào bên trong hàm init ().
Cú pháp
init() {
//New Instance initialization goes here
}
Thí dụ
struct rectangle {
var length: Double
var breadth: Double
init() {
length = 6
breadth = 12
}
}
var area = rectangle()
print("area of rectangle is \(area.length*area.breadth)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
area of rectangle is 72.0
Ở đây cấu trúc 'hình chữ nhật' được khởi tạo với chiều dài và chiều rộng thành viên là kiểu dữ liệu 'Đôi'. Phương thức Init () được sử dụng để khởi tạo các giá trị cho chiều dài thành viên mới được tạo và nhân đôi. Diện tích hình chữ nhật được tính và trả về bằng cách gọi hàm hình chữ nhật.
Đặt giá trị thuộc tính theo mặc định
Ngôn ngữ Swift 4 cung cấp hàm Init () để khởi tạo các giá trị thuộc tính được lưu trữ. Ngoài ra, người dùng có quyền khởi tạo các giá trị thuộc tính theo mặc định trong khi khai báo các thành viên lớp hoặc cấu trúc. Khi thuộc tính nhận cùng một giá trị trong suốt chương trình, chúng ta có thể khai báo nó trong phần khai báo một mình thay vì khởi tạo nó trong init (). Đặt giá trị thuộc tính theo mặc định cho phép người dùng khi kế thừa được xác định cho các lớp hoặc cấu trúc.
struct rectangle {
var length = 6
var breadth = 12
}
var area = rectangle()
print("area of rectangle is \(area.length*area.breadth)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
area of rectangle is 72
Ở đây thay vì khai báo độ dài và độ rộng trong init (), các giá trị được khởi tạo trong chính khai báo.
Khởi tạo tham số
Trong ngôn ngữ Swift 4, người dùng có quyền khởi tạo các tham số như một phần của định nghĩa trình khởi tạo bằng cách sử dụng init ().
struct Rectangle {
var length: Double
var breadth: Double
var area: Double
init(fromLength length: Double, fromBreadth breadth: Double) {
self.length = length
self.breadth = breadth
area = length * breadth
}
init(fromLeng leng: Double, fromBread bread: Double) {
self.length = leng
self.breadth = bread
area = leng * bread
}
}
let ar = Rectangle(fromLength: 6, fromBreadth: 12)
print("area is: \(ar.area)")
let are = Rectangle(fromLeng: 36, fromBread: 12)
print("area is: \(are.area)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
area is: 72.0
area is: 432.0
Tham số cục bộ & bên ngoài
Tham số khởi tạo có cả tên tham số cục bộ và toàn cục tương tự như tên tham số hàm và phương thức. Khai báo tham số cục bộ được sử dụng để truy cập bên trong thân khởi tạo và khai báo tham số bên ngoài được sử dụng để gọi bộ khởi tạo. Bộ khởi tạo Swift 4 khác với bộ khởi tạo chức năng và phương thức là chúng không xác định bộ khởi tạo nào được sử dụng để gọi hàm nào.
Để khắc phục điều này, Swift 4 giới thiệu một tên bên ngoài tự động cho mỗi và mọi tham số trong init (). Tên bên ngoài tự động này tương đương với tên cục bộ được viết trước mọi tham số khởi tạo.
struct Days {
let sunday, monday, tuesday: Int
init(sunday: Int, monday: Int, tuesday: Int) {
self.sunday = sunday
self.monday = monday
self.tuesday = tuesday
}
init(daysofaweek: Int) {
sunday = daysofaweek
monday = daysofaweek
tuesday = daysofaweek
}
}
let week = Days(sunday: 1, monday: 2, tuesday: 3)
print("Days of a Week is: \(week.sunday)")
print("Days of a Week is: \(week.monday)")
print("Days of a Week is: \(week.tuesday)")
let weekdays = Days(daysofaweek: 4)
print("Days of a Week is: \(weekdays.sunday)")
print("Days of a Week is: \(weekdays.monday)")
print("Days of a Week is: \(weekdays.tuesday)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Days of a Week is: 1
Days of a Week is: 2
Days of a Week is: 3
Days of a Week is: 4
Days of a Week is: 4
Days of a Week is: 4
Tham số không có tên bên ngoài
Khi tên bên ngoài không cần thiết cho dấu gạch dưới khởi tạo '_' được sử dụng để ghi đè hành vi mặc định.
struct Rectangle {
var length: Double
init(frombreadth breadth: Double) {
length = breadth * 10
}
init(frombre bre: Double) {
length = bre * 30
}
init(_ area: Double) {
length = area
}
}
let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")
let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")
let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
area is: 180.0
area is: 370.0
area is: 110.0
Các loại tài sản tùy chọn
Khi thuộc tính được lưu trữ tại một số trường hợp không trả về bất kỳ giá trị nào thì thuộc tính đó được khai báo với kiểu 'tùy chọn' cho biết rằng 'không có giá trị' được trả về cho kiểu cụ thể đó. Khi thuộc tính được lưu trữ được khai báo là 'tùy chọn', nó sẽ tự động khởi tạo giá trị thành 'nil' trong quá trình khởi tạo chính nó.
struct Rectangle {
var length: Double?
init(frombreadth breadth: Double) {
length = breadth * 10
}
init(frombre bre: Double) {
length = bre * 30
}
init(_ area: Double) {
length = area
}
}
let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")
let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")
let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)
Sửa đổi các thuộc tính không đổi trong quá trình khởi tạo
Khởi tạo cũng cho phép người dùng sửa đổi giá trị của thuộc tính hằng số. Trong quá trình khởi tạo, thuộc tính lớp cho phép các cá thể lớp của nó được sửa đổi bởi lớp siêu chứ không phải lớp con. Hãy xem xét ví dụ trong chương trình trước, 'độ dài' được khai báo là 'biến' trong lớp chính. Biến chương trình dưới đây 'length' được sửa đổi thành biến 'hằng số'.
struct Rectangle {
let length: Double?
init(frombreadth breadth: Double) {
length = breadth * 10
}
init(frombre bre: Double) {
length = bre * 30
}
init(_ area: Double) {
length = area
}
}
let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")
let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")
let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)
Bộ khởi tạo mặc định
Bộ khởi tạo mặc định cung cấp một thể hiện mới cho tất cả các thuộc tính đã khai báo của lớp cơ sở hoặc cấu trúc với các giá trị mặc định.
class defaultexample {
var studname: String?
var stmark = 98
var pass = true
}
var result = defaultexample()
print("result is: \(result.studname)")
print("result is: \(result.stmark)")
print("result is: \(result.pass)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau. -
result is: nil
result is: 98
result is: true
Chương trình trên được định nghĩa với tên lớp là 'defaultexample'. Ba hàm thành viên được khởi tạo theo mặc định là 'studname?' để lưu trữ các giá trị 'nil', 'stmark' là 98 và 'pass' là giá trị Boolean 'true'. Tương tự như vậy, các giá trị thành viên trong lớp có thể được khởi tạo mặc định trước khi xử lý các kiểu thành viên của lớp.
Thành viên khởi tạo cho các loại cấu trúc
Khi người dùng không cung cấp trình khởi tạo tùy chỉnh, các loại Cấu trúc trong Swift 4 sẽ tự động nhận 'trình khởi tạo thành viên'. Chức năng chính của nó là khởi tạo các cá thể cấu trúc mới với khởi tạo thành viên mặc định và sau đó các thuộc tính của cá thể mới được chuyển cho khởi tạo thành viên theo tên.
struct Rectangle {
var length = 100.0, breadth = 200.0
}
let area = Rectangle(length: 24.0, breadth: 32.0)
print("Area of rectangle is: \(area.length)")
print("Area of rectangle is: \(area.breadth)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Area of rectangle is: 24.0
Area of rectangle is: 32.0
Các cấu trúc được khởi tạo theo mặc định cho các chức năng thành viên của chúng trong quá trình khởi tạo cho 'chiều dài' là '100.0' và 'chiều rộng' là '200.0'. Nhưng các giá trị bị ghi đè trong quá trình xử lý các biến chiều dài và chiều rộng là 24.0 và 32.0.
Ủy quyền trình khởi tạo cho các loại giá trị
Ủy quyền khởi tạo được định nghĩa là việc gọi các trình khởi tạo từ các trình khởi tạo khác. Chức năng chính của nó là hoạt động như khả năng tái sử dụng để tránh trùng lặp mã trên nhiều bộ khởi tạo.
struct Stmark {
var mark1 = 0.0, mark2 = 0.0
}
struct stdb {
var m1 = 0.0, m2 = 0.0
}
struct block {
var average = stdb()
var result = Stmark()
init() {}
init(average: stdb, result: Stmark) {
self.average = average
self.result = result
}
init(avg: stdb, result: Stmark) {
let tot = avg.m1 - (result.mark1 / 2)
let tot1 = avg.m2 - (result.mark2 / 2)
self.init(average: stdb(m1: tot, m2: tot1), result: result)
}
}
let set1 = block()
print("student result is: \(set1.average.m1, set1.average.m2)
\(set1.result.mark1, set1.result.mark2)")
let set2 = block(average: stdb(m1: 2.0, m2: 2.0),
result: Stmark(mark1: 5.0, mark2: 5.0))
print("student result is: \(set2.average.m1, set2.average.m2)
\(set2.result.mark1, set2.result.mark2)")
let set3 = block(avg: stdb(m1: 4.0, m2: 4.0),
result: Stmark(mark1: 3.0, mark2: 3.0))
print("student result is: \(set3.average.m1, set3.average.m2)
\(set3.result.mark1, set3.result.mark2)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
(0.0,0.0) (0.0,0.0)
(2.0,2.0) 5.0,5.0)
(2.5,2.5) (3.0,3.0)
Quy tắc ủy quyền trình khởi tạo
Các loại giá trị | Các loại lớp |
---|---|
Kế thừa không được hỗ trợ cho các loại giá trị như cấu trúc và liệt kê. Tham khảo các trình khởi tạo khác được thực hiện thông qua self.init | Kế thừa được hỗ trợ. Kiểm tra tất cả các giá trị thuộc tính được lưu trữ được khởi tạo |
Kế thừa và Khởi tạo Lớp
Các kiểu lớp có hai loại trình khởi tạo để kiểm tra xem các thuộc tính được lưu trữ đã xác định có nhận giá trị ban đầu hay không, cụ thể là trình khởi tạo được chỉ định và trình khởi tạo tiện lợi.
Bộ khởi tạo được chỉ định và Bộ khởi tạo tiện lợi
Bộ khởi tạo được chỉ định | Trình khởi tạo Tiện lợi |
---|---|
Được coi là khởi tạo chính cho một lớp | Được coi là hỗ trợ khởi tạo cho một lớp |
Tất cả các thuộc tính của lớp đều được khởi tạo và bộ khởi tạo siêu lớp thích hợp được gọi để khởi tạo thêm | Bộ khởi tạo được chỉ định được gọi với bộ khởi tạo tiện lợi để tạo cá thể lớp cho một trường hợp sử dụng cụ thể hoặc kiểu giá trị đầu vào |
Ít nhất một bộ khởi tạo được chỉ định được xác định cho mọi lớp | Không cần phải xác định bắt buộc các trình khởi tạo tiện lợi khi lớp không yêu cầu trình khởi tạo. |
Init (tham số) {câu lệnh} | tiện ích init (tham số) {câu lệnh} |
Chương trình cho Bộ khởi tạo được Chỉ định
class mainClass {
var no1 : Int // local storage
init(no1 : Int) {
self.no1 = no1 // initialization
}
}
class subClass : mainClass {
var no2 : Int // new subclass storage
init(no1 : Int, no2 : Int) {
self.no2 = no2 // initialization
super.init(no1:no1) // redirect to superclass
}
}
let res = mainClass(no1: 10)
let print = subClass(no1: 10, no2: 20)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
res is: 10
res is: 10
res is: 20
Chương trình khởi tạo tiện lợi
class mainClass {
var no1 : Int // local storage
init(no1 : Int) {
self.no1 = no1 // initialization
}
}
class subClass : mainClass {
var no2 : Int
init(no1 : Int, no2 : Int) {
self.no2 = no2
super.init(no1:no1)
}
// Requires only one parameter for convenient method
override convenience init(no1: Int) {
self.init(no1:no1, no2:0)
}
}
let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
res is: 20
res is: 30
res is: 50
Kế thừa và Ghi đè khởi tạo
Swift 4 không cho phép các lớp con của nó kế thừa các bộ khởi tạo lớp cha của nó cho các kiểu thành viên của chúng theo mặc định. Tính kế thừa chỉ áp dụng cho các bộ khởi tạo siêu hạng ở một mức độ nào đó sẽ được thảo luận trong Kế thừa bộ khởi tạo tự động.
Khi người dùng cần có các trình khởi tạo được xác định trong siêu lớp, thì lớp con với các trình khởi tạo phải được người dùng xác định là triển khai tùy chỉnh. Khi ghi đè phải được thực hiện bởi lớp con thì từ khóa 'ghi đè' của lớp siêu phải được khai báo.
class sides {
var corners = 4
var description: String {
return "\(corners) sides"
}
}
let rectangle = sides()
print("Rectangle: \(rectangle.description)")
class pentagon: sides {
override init() {
super.init()
corners = 5
}
}
let bicycle = pentagon()
print("Pentagon: \(bicycle.description)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Rectangle: 4 sides
Pentagon: 5 sides
Công cụ khởi tạo được chỉ định và thuận tiện trong hành động
class Planet {
var name: String
init(name: String) {
self.name = name
}
convenience init() {
self.init(name: "[No Planets]")
}
}
let plName = Planet(name: "Mercury")
print("Planet name is: \(plName.name)")
let noplName = Planet()
print("No Planets like that: \(noplName.name)")
class planets: Planet {
var count: Int
init(name: String, count: Int) {
self.count = count
super.init(name: name)
}
override convenience init(name: String) {
self.init(name: name, count: 1)
}
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Planet name is: Mercury
No Planets like that: [No Planets]
Bộ khởi tạo khả dụng
Người dùng phải được thông báo khi có bất kỳ lỗi khởi tạo nào trong khi xác định một lớp, cấu trúc hoặc các giá trị liệt kê. Việc khởi tạo các biến đôi khi trở thành một lỗi do−
- Giá trị tham số không hợp lệ.
- Thiếu nguồn bên ngoài cần thiết.
- Điều kiện ngăn quá trình khởi tạo thành công.
Để bắt các ngoại lệ do phương thức khởi tạo ném ra, Swift 4 tạo ra một khởi tạo linh hoạt được gọi là 'bộ khởi tạo khả dụng' để thông báo cho người dùng rằng có điều gì đó không được chú ý trong khi khởi tạo cấu trúc, lớp hoặc thành viên liệt kê. Từ khóa để bắt trình khởi tạo có sẵn là 'init?'. Ngoài ra, các bộ khởi tạo có sẵn và không khả dụng không thể được xác định với các kiểu và tên tham số giống nhau.
struct studrecord {
let stname: String
init?(stname: String) {
if stname.isEmpty {return nil }
self.stname = stname
}
}
let stmark = studrecord(stname: "Swing")
if let name = stmark {
print("Student name is specified")
}
let blankname = studrecord(stname: "")
if blankname == nil {
print("Student name is left blank")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Student name is specified
Student name is left blank
Các công cụ khởi tạo khả dụng cho kê khai
Ngôn ngữ Swift 4 cung cấp sự linh hoạt để có các bộ khởi tạo sẵn có cho các bảng liệt kê để thông báo cho người dùng khi các thành viên của bảng liệt kê không còn khởi tạo các giá trị.
enum functions {
case a, b, c, d
init?(funct: String) {
switch funct {
case "one":
self = .a
case "two":
self = .b
case "three":
self = .c
case "four":
self = .d
default:
return nil
}
}
}
let result = functions(funct: "two")
if result != nil {
print("With In Block Two")
}
let badresult = functions(funct: "five")
if badresult == nil {
print("Block Does Not Exist")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
With In Block Two
Block Does Not Exist
Trình khởi tạo khả dụng cho các lớp
Một bộ khởi tạo khả dụng khi được khai báo với các kiểu liệt kê và cấu trúc sẽ cảnh báo lỗi khởi tạo trong bất kỳ trường hợp nào trong quá trình triển khai nó. Tuy nhiên, bộ khởi tạo khả dụng trong các lớp sẽ chỉ cảnh báo lỗi sau khi các thuộc tính được lưu trữ đã được đặt thành giá trị ban đầu.
class studrecord {
let studname: String!
init?(studname: String) {
self.studname = studname
if studname.isEmpty { return nil }
}
}
if let stname = studrecord(studname: "Failable Initializers") {
print("Module is \(stname.studname)")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Module is Optional("Failable Initializers")
Ghi đè một trình khởi tạo khả dụng
Giống như khởi tạo, người dùng cũng có điều kiện ghi đè một bộ khởi tạo sẵn có của lớp cha bên trong lớp con. Khởi tạo khả dụng siêu lớp cũng có thể được ghi đè trong một trình khởi tạo không khả dụng của lớp con.
Bộ khởi tạo lớp con không thể ủy quyền cho bộ khởi tạo lớp con khi ghi đè một bộ khởi tạo lớp siêu khả dụng bằng một lần khởi tạo lớp con không khả dụng.
Bộ khởi tạo không khả dụng không bao giờ có thể ủy quyền cho bộ khởi tạo khả dụng.
Chương trình đưa ra dưới đây mô tả các bộ khởi tạo khả dụng và không khả dụng.
class Planet {
var name: String
init(name: String) {
self.name = name
}
convenience init() {
self.init(name: "[No Planets]")
}
}
let plName = Planet(name: "Mercury")
print("Planet name is: \(plName.name)")
let noplName = Planet()
print("No Planets like that: \(noplName.name)")
class planets: Planet {
var count: Int
init(name: String, count: Int) {
self.count = count
super.init(name: name)
}
override convenience init(name: String) {
self.init(name: name, count: 1)
}
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Planet name is: Mercury
No Planets like that: [No Planets]
Init! Bộ khởi tạo khả dụng
Swift 4 cung cấp 'init?' để xác định một bộ khởi tạo có sẵn phiên bản tùy chọn. Để xác định một phiên bản tùy chọn không được bao bọc hoàn toàn của kiểu cụ thể 'init!' được quy định.
struct studrecord {
let stname: String
init!(stname: String) {
if stname.isEmpty {return nil }
self.stname = stname
}
}
let stmark = studrecord(stname: "Swing")
if let name = stmark {
print("Student name is specified")
}
let blankname = studrecord(stname: "")
if blankname == nil {
print("Student name is left blank")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Student name is specified
Student name is left blank
Bộ khởi tạo bắt buộc
Để khai báo từng và mọi lớp con của từ khóa khởi tạo 'bắt buộc' cần phải được xác định trước hàm init ().
class classA {
required init() {
var a = 10
print(a)
}
}
class classB: classA {
required init() {
var b = 30
print(b)
}
}
let res = classA()
let print = classB()
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
10
30
10
Trước khi một cá thể lớp cần được phân bổ, 'deinitializer' phải được gọi để phân bổ không gian bộ nhớ. Từ khóa 'deinit' được sử dụng để phân bổ không gian bộ nhớ bị chiếm bởi tài nguyên hệ thống. Deinitialization chỉ có sẵn trên các loại lớp.
Deinitialization để phân bổ không gian bộ nhớ
Swift 4 tự động phân bổ các phiên bản của bạn khi chúng không còn cần thiết để giải phóng tài nguyên. Swift 4 xử lý việc quản lý bộ nhớ của các cá thể thông qua đếm tham chiếu tự động (ARC), như được mô tả trong Đếm tham chiếu tự động. Thông thường, bạn không cần thực hiện dọn dẹp thủ công khi các phiên bản của bạn được phân bổ. Tuy nhiên, khi bạn đang làm việc với các tài nguyên của mình, bạn có thể cần phải tự mình thực hiện thêm một số thao tác dọn dẹp. Ví dụ: nếu bạn tạo một lớp tùy chỉnh để mở một tệp và ghi một số dữ liệu vào nó, bạn có thể cần phải đóng tệp trước khi cá thể lớp được phân bổ.
var counter = 0; // for reference counting
class baseclass {
init() {
counter++;
}
deinit {
counter--;
}
}
var print: baseclass? = baseclass()
print(counter)
print = nil
print(counter)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
1
0
Khi câu lệnh print = nil bị bỏ qua, các giá trị của bộ đếm vẫn giữ nguyên vì nó không bị khử hóa.
var counter = 0; // for reference counting
class baseclass {
init() {
counter++;
}
deinit {
counter--;
}
}
var print: baseclass? = baseclass()
print(counter)
print(counter)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
1
1
Các chức năng quản lý bộ nhớ và việc sử dụng nó được xử lý bằng ngôn ngữ Swift 4 thông qua Đếm tham chiếu tự động (ARC). ARC được sử dụng để khởi tạo và khởi tạo tài nguyên hệ thống, do đó giải phóng không gian bộ nhớ được sử dụng bởi các cá thể lớp khi các cá thể không còn cần thiết nữa. ARC theo dõi thông tin về mối quan hệ giữa các trường hợp mã của chúng ta để quản lý tài nguyên bộ nhớ một cách hiệu quả.
Chức năng của ARC
ARC cấp phát một phần bộ nhớ để lưu trữ thông tin mỗi khi một cá thể lớp mới được tạo bởi init ().
Thông tin về kiểu thể hiện và các giá trị của nó được lưu trong bộ nhớ.
Khi cá thể lớp không còn cần thiết nữa, nó sẽ tự động giải phóng không gian bộ nhớ bằng deinit () để lưu trữ và truy xuất cá thể lớp khác.
ARC theo dõi các thuộc tính, hằng số và biến của các cá thể lớp hiện đang tham chiếu để deinit () chỉ được áp dụng cho những cá thể không sử dụng đó.
ARC duy trì một 'tham chiếu mạnh' đến thuộc tính, hằng số và biến thể hiện của lớp đó để hạn chế việc phân bổ khi cá thể lớp hiện đang được sử dụng.
Chương trình ARC
class StudDetails {
var stname: String!
var mark: Int!
init(stname: String, mark: Int) {
self.stname = stname
self.mark = mark
}
deinit {
print("Deinitialized \(self.stname)")
print("Deinitialized \(self.mark)")
}
}
let stname = "Swift 4"
let mark = 98
print(stname)
print(mark)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Swift 4
98
Phiên bản lớp chu kỳ tham chiếu mạnh mẽ của ARC
class studmarks {
let name: String
var stud: student?
init (name: String) {
print("Initializing: \(name)")
self.name = name
}
deinit {
print("Deallocating: \(self.name)")
}
}
class student {
let name: String
var strname: studmarks?
init (name: String) {
print("Initializing: \(name)")
self.name = name
}
deinit {
print("Deallocating: \(self.name)")
}
}
var shiba: studmarks?
var mari: student?
shiba = studmarks(name: "Swift 4")
mari = student(name: "ARC")
shiba!.stud = mari
mari!.strname = shiba
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Initializing: Swift 4
Initializing: ARC
Tài liệu tham khảo yếu và chưa được biết đến của ARC
Thuộc tính kiểu lớp có hai cách để giải quyết các chu trình tham chiếu mạnh:
- Tài liệu tham khảo yếu
- Tài liệu tham khảo chưa biết
Các tham chiếu này được sử dụng để cho phép một cá thể này tham chiếu các cá thể khác trong một chu trình tham chiếu. Sau đó, các cá thể có thể tham chiếu đến từng và mọi trường hợp thay vì quan tâm đến chu trình tham chiếu mạnh. Khi người dùng biết rằng một số phiên bản có thể trả về giá trị 'nil', chúng tôi có thể chỉ ra rằng sử dụng tham chiếu yếu. Khi instance sẽ trả về một cái gì đó thay vì nil thì hãy khai báo nó với tham chiếu không xác định.
Chương trình tham chiếu yếu
class module {
let name: String
init(name: String) { self.name = name }
var sub: submodule?
deinit { print("\(name) Is The Main Module") }
}
class submodule {
let number: Int
init(number: Int) { self.number = number }
weak var topic: module?
deinit { print("Sub Module with its topic number is \(number)") }
}
var toc: module?
var list: submodule?
toc = module(name: "ARC")
list = submodule(number: 4)
toc!.sub = list
list!.topic = toc
toc = nil
list = nil
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
ARC Is The Main Module
Sub Module with its topic number is 4
Chương trình tham khảo chưa được biết đến
class student {
let name: String
var section: marks?
init(name: String) {
self.name = name
}
deinit { print("\(name)") }
}
class marks {
let marks: Int
unowned let stname: student
init(marks: Int, stname: student) {
self.marks = marks
self.stname = stname
}
deinit { print("Marks Obtained by the student is \(marks)") }
}
var module: student?
module = student(name: "ARC")
module!.section = marks(marks: 98, stname: module!)
module = nil
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
ARC
Marks Obtained by the student is 98
Các chu trình tham chiếu mạnh mẽ để đóng cửa
Khi chúng ta gán một bao đóng cho thuộc tính cá thể lớp và cho phần thân của bao đóng để nắm bắt chu trình tham chiếu mạnh của cá thể cụ thể có thể xảy ra. Tham chiếu mạnh mẽ đến bao đóng được định nghĩa bởi 'self.someProperty' hoặc 'self.someMethod ()'. Các chu kỳ tham chiếu mạnh được sử dụng làm loại tham chiếu cho các lần đóng cửa.
class HTMLElement {
let samplename: String
let text: String?
lazy var asHTML: () -> String = {
if let text = self.text {
return "<\(self.samplename)>\(text)</\(self.samplename)>"
} else {
return "<\(self.samplename) />"
}
}
init(samplename: String, text: String? = nil) {
self.samplename = samplename
self.text = text
}
deinit {
print("\(samplename) is being deinitialized")
}
}
var paragraph: HTMLElement? = HTMLElement(samplename: "p", text: "Welcome to Closure SRC")
print(paragraph!.asHTML())
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
<p>Welcome to Closure SRC</p>
Tài liệu tham khảo yếu và chưa được biết đến
Khi bao đóng và cá thể tham chiếu đến nhau, người dùng có thể xác định việc nắm bắt trong một bao đóng là một tham chiếu không xác định. Sau đó, nó sẽ không cho phép người dùng phân bổ cá thể cùng một lúc. Khi cá thể một lúc nào đó trả về giá trị 'nil' xác định việc đóng với cá thể yếu.
class HTMLElement {
let module: String
let text: String?
lazy var asHTML: () -> String = {
[unowned self] in
if let text = self.text {
return "<\(self.module)>\(text)</\(self.module)>"
} else {
return "<\(self.module) />"
}
}
init(module: String, text: String? = nil) {
self.module = module
self.text = text
}
deinit {
print("\(module) the deinit()")
}
}
var paragraph: HTMLElement? = HTMLElement(module: "Inside", text: "ARC Weak References")
print(paragraph!.asHTML())
paragraph = nil
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
<Inside>ARC Weak References</Inside>
Inside the deinit()
Quá trình truy vấn, gọi thuộc tính, chỉ số con và phương thức trên một tùy chọn có thể là 'nil' được định nghĩa là chuỗi tùy chọn. Chuỗi tùy chọn trả về hai giá trị -
nếu tùy chọn chứa 'giá trị' thì việc gọi thuộc tính, phương thức và chỉ số con liên quan của nó sẽ trả về giá trị
nếu tùy chọn chứa giá trị 'nil' thì tất cả thuộc tính, phương thức và chỉ số con liên quan của nó sẽ trả về nil
Vì nhiều truy vấn đến các phương thức, các thuộc tính và chỉ số con được nhóm lại với nhau, việc không thành một chuỗi sẽ ảnh hưởng đến toàn bộ chuỗi và dẫn đến giá trị 'nil'.
Chuỗi tùy chọn như một biện pháp thay thế cho việc buộc mở gói
Chuỗi tùy chọn được chỉ định sau giá trị tùy chọn bằng '?' để gọi một thuộc tính, phương thức hoặc chỉ số con khi giá trị tùy chọn trả về một số giá trị.
Chuỗi tùy chọn '?' | Truy cập vào các phương thức, thuộc tính và subcripts Chuỗi tùy chọn '!' để buộc Unwrapping |
? được đặt sau giá trị tùy chọn để gọi thuộc tính, phương thức hoặc chỉ số con | ! được đặt sau giá trị tùy chọn để gọi thuộc tính, phương thức hoặc chỉ số con để buộc bỏ gói giá trị |
Không thành công khi tùy chọn là 'nil' | Việc mở gói cưỡng bức gây ra lỗi thời gian chạy khi tùy chọn là 'nil' |
Chương trình Chuỗi tùy chọn với '!'
class ElectionPoll {
var candidate: Pollbooth?
}
lass Pollbooth {
var name = "MP"
}
let cand = ElectionPoll()
let candname = cand.candidate!.name
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
fatal error: unexpectedly found nil while unwrapping an Optional value
0 Swift 4 0x0000000103410b68
llvm::sys::PrintStackTrace(__sFILE*) + 40
1 Swift 4 0x0000000103411054 SignalHandler(int) + 452
2 libsystem_platform.dylib 0x00007fff9176af1a _sigtramp + 26
3 libsystem_platform.dylib 0x000000000000000b _sigtramp + 1854492939
4 libsystem_platform.dylib 0x00000001074a0214 _sigtramp + 1976783636
5 Swift 4 0x0000000102a85c39
llvm::JIT::runFunction(llvm::Function*, std::__1::vector > const&) + 329
6 Swift 4 0x0000000102d320b3
llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*,
std::__1::vector<std::__1::basic_string, std::__1::allocator >,
std::__1::allocator<std::__1::basic_string, std::__1::allocator > > > const&,
char const* const*) + 1523
7 Swift 4 0x000000010296e6ba Swift 4::RunImmediately(Swift
4::CompilerInstance&, std::__1::vector<std::__1::basic_string,
std::__1::allocator >, std::__1::allocator<std::__1::basic_string,
std::__1::allocator > > > const&, Swift 4::IRGenOptions&, Swift 4::SILOptions
const&) + 1066
8 Swift 4 0x000000010275764b frontend_main(llvm::ArrayRef,
char const*, void*) + 5275
9 Swift 4 0x0000000102754a6d main + 1677
10 libdyld.dylib 0x00007fff8bb9e5c9 start + 1
11 libdyld.dylib 0x000000000000000c start + 1950751300
Stack dump:
0. Program arguments:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/
usr/bin/Swift 4 -frontend -interpret - -target x86_64-apple-darwin14.0.0 -
target-cpu core2 -sdk
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/
SDKs/MacOSX10.10.sdk -module-name main
/bin/sh: line 47: 15672 Done cat <<'SWIFT 4'
import Foundation
</std::__1::basic_string</std::__1::basic_string</std::__1::basic_string</std::
__1::basic_string
Chương trình trên tuyên bố 'cuộc thăm dò bầu cử' là tên lớp và chứa 'ứng cử viên' làm chức năng thành viên. Lớp con được khai báo là 'gian hàng thăm dò ý kiến' và 'tên' là chức năng thành viên của nó được khởi tạo là 'MP'. Lời gọi đến lớp siêu được khởi tạo bằng cách tạo một thể hiện 'cand' với tùy chọn '!'. Vì các giá trị không được khai báo trong lớp cơ sở của nó, nên giá trị 'nil' được lưu trữ do đó trả về một lỗi nghiêm trọng bằng thủ tục buộc mở gói.
Chương trình cho Chuỗi tùy chọn với '?'
class ElectionPoll {
var candidate: Pollbooth?
}
class Pollbooth {
var name = "MP"
}
let cand = ElectionPoll()
if let candname = cand.candidate?.name {
print("Candidate name is \(candname)")
} else {
print("Candidate name cannot be retreived")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Candidate name cannot be retreived
Chương trình trên khai báo 'cuộc thăm dò bầu cử' là tên lớp và chứa 'ứng cử viên' làm chức năng thành viên. Lớp con được khai báo là 'gian hàng thăm dò ý kiến' và 'tên' là chức năng thành viên của nó được khởi tạo là 'MP'. Lời gọi đến lớp siêu được khởi tạo bằng cách tạo một thể hiện 'cand' với tùy chọn '?'. Vì các giá trị không được khai báo trong lớp cơ sở nên giá trị 'nil' được lưu trữ và in trong bảng điều khiển bởi khối trình xử lý khác.
Xác định các lớp mô hình cho các thuộc tính truy cập và chuỗi tùy chọn
Ngôn ngữ Swift 4 cũng cung cấp khái niệm về chuỗi tùy chọn, để khai báo nhiều hơn một lớp con dưới dạng các lớp mô hình. Khái niệm này sẽ rất hữu ích để xác định các mô hình phức tạp và để truy cập các thuộc tính, phương thức và thuộc tính con subscript.
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var street: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let rectname = rectangle()
if let rectarea = rectname.print?.cprint {
print("Area of rectangle is \(rectarea)")
} else {
print("Rectangle Area is not specified")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Rectangle Area is not specified
Phương thức gọi thông qua chuỗi tùy chọn
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("Area of Circle is: \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
if circname.print?.circleprint() != nil {
print("Area of circle is specified)")
} else {
print("Area of circle is not specified")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Area of circle is not specified
Hàm circleprint () được khai báo bên trong lớp con circle () được gọi bằng cách tạo một thể hiện có tên là "circlename". Hàm sẽ trả về một giá trị nếu nó chứa một số giá trị, nếu không nó sẽ trả về một số thông báo in do người dùng xác định bằng cách kiểm tra câu lệnh 'if circlename.print? .Circleprint ()! = Nil'.
Truy cập Đăng ký thông qua Chuỗi tùy chọn
Chuỗi tùy chọn được sử dụng để đặt và truy xuất một giá trị chỉ số con để xác thực xem liệu lệnh gọi đến chỉ số con đó có trả về giá trị hay không. '?' được đặt trước dấu ngoặc nhọn chỉ số con để truy cập giá trị tùy chọn trên chỉ số con cụ thể.
Chương trình 1
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
if let radiusName = circname.print?[0].radiusname {
print("The first room name is \(radiusName).")
} else {
print("Radius is not specified.")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Radius is not specified.
Trong chương trình trên, các giá trị cá thể cho hàm thành viên 'radiusName' không được chỉ định. Do đó, lệnh gọi của chương trình tới hàm sẽ chỉ trả về một phần khác trong khi để trả về các giá trị mà chúng ta phải xác định các giá trị cho hàm thành viên cụ thể.
Chương trình 2
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")
let printing = circle()
printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing
if let radiusName = circname.print?[0].radiusname {
print("Radius is measured in \(radiusName).")
} else {
print("Radius is not specified.")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Radius is measured in Units.
Trong chương trình trên, các giá trị cá thể cho hàm thành viên 'radiusName' được chỉ định. Do đó, chương trình gọi hàm sẽ trả về giá trị.
Truy cập các đăng ký thuộc loại tùy chọn
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")
let printing = circle()
printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing
var area = ["Radius": [35, 45, 78, 101], "Circle": [90, 45, 56]]
area["Radius"]?[1] = 78
area["Circle"]?[1]--
print(area["Radius"]?[0])
print(area["Radius"]?[1])
print(area["Radius"]?[2])
print(area["Radius"]?[3])
print(area["Circle"]?[0])
print(area["Circle"]?[1])
print(area["Circle"]?[2])
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Optional(35)
Optional(78)
Optional(78)
Optional(101)
Optional(90)
Optional(44)
Optional(56)
Các giá trị tùy chọn cho chỉ số phụ có thể được truy cập bằng cách tham chiếu các giá trị chỉ số phụ của chúng. Nó có thể được truy cập dưới dạng chỉ số dưới [0], chỉ số dưới [1], v.v. Các giá trị chỉ số dưới mặc định cho 'bán kính' lần đầu tiên được gán là [35, 45, 78, 101] và cho 'Vòng tròn' [90, 45, 56]] . Sau đó, các giá trị chỉ số con được thay đổi như Radius [0] thành 78 và Circle [1] thành 45.
Liên kết nhiều cấp độ của chuỗi
Nhiều lớp con cũng có thể được liên kết với các phương thức, thuộc tính và chỉ số con siêu lớp của nó bằng chuỗi tùy chọn.
Nhiều chuỗi tùy chọn có thể được liên kết -
Nếu loại truy xuất không phải là tùy chọn, chuỗi tùy chọn sẽ trả về một giá trị tùy chọn. Ví dụ: nếu Chuỗi thông qua chuỗi tùy chọn, nó sẽ trả về Chuỗi? Giá trị
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
if let radiusName = circname.print?[0].radiusname {
print("The first room name is \(radiusName).")
} else {
print("Radius is not specified.")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Radius is not specified.
Trong chương trình trên, các giá trị cá thể cho hàm thành viên 'radiusName' không được chỉ định. Do đó, lệnh gọi chương trình đến hàm sẽ chỉ trả về một phần khác trong khi trả về các giá trị mà chúng ta phải xác định các giá trị cho hàm thành viên cụ thể.
Nếu kiểu truy xuất đã là tùy chọn, thì chuỗi tùy chọn cũng sẽ trả về một giá trị tùy chọn. Ví dụ nếu String? Được truy cập thông qua chuỗi tùy chọn nó sẽ trả về Chuỗi? Giá trị..
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")
let printing = circle()
printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing
if let radiusName = circname.print?[0].radiusname {
print("Radius is measured in \(radiusName).")
} else {
print("Radius is not specified.")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Radius is measured in Units.
Trong chương trình trên, các giá trị cá thể cho hàm thành viên 'radiusName' được chỉ định. Do đó, lệnh gọi chương trình đến hàm bây giờ sẽ trả về giá trị.
Chuỗi theo các phương pháp có giá trị trả lại tùy chọn
Chuỗi tùy chọn cũng được sử dụng để truy cập các phương thức được xác định của lớp con.
class rectangle {
var print: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("Area of Circle is: \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
if circname.print?.circleprint() != nil {
print("Area of circle is specified)")
} else {
print("Area of circle is not specified")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Area of circle is not specified
Để xác thực kiểu của một phiên bản, 'Truyền kiểu' có tác dụng trong ngôn ngữ Swift 4. Nó được sử dụng để kiểm tra xem kiểu thể hiện có thuộc về một siêu lớp hoặc lớp con cụ thể hay nó được định nghĩa trong hệ thống phân cấp của chính nó.
Ép kiểu Swift 4 cung cấp hai toán tử 'là' để kiểm tra kiểu của một giá trị và 'as' và để ép kiểu giá trị sang một kiểu khác. Truyền kiểu cũng kiểm tra xem kiểu cá thể có tuân theo tiêu chuẩn tuân thủ giao thức cụ thể hay không.
Xác định một hệ thống phân cấp lớp
Kiểu ép kiểu được sử dụng để kiểm tra kiểu thể hiện để tìm hiểu xem nó có thuộc kiểu lớp cụ thể hay không. Ngoài ra, nó kiểm tra phân cấp của các lớp và các lớp con của nó để kiểm tra và ép kiểu các thể hiện đó để biến nó thành một hệ thống phân cấp giống nhau.
class Subjects {
var physics: String
init(physics: String) {
self.physics = physics
}
}
class Chemistry: Subjects {
var equations: String
init(physics: String, equations: String) {
self.equations = equations
super.init(physics: physics)
}
}
class Maths: Subjects {
var formulae: String
init(physics: String, formulae: String) {
self.formulae = formulae
super.init(physics: physics)
}
}
let sa = [ Chemistry(physics: "solid physics", equations: "Hertz"),
Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")]
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Kiểm tra loại
Kiểm tra loại được thực hiện với toán tử 'là'. Toán tử kiểm tra kiểu 'is' kiểm tra xem cá thể có thuộc loại lớp con cụ thể hay không và trả về 'true' nếu nó thuộc về cá thể đó nếu không nó sẽ trả về 'false'.
class Subjects {
var physics: String
init(physics: String) {
self.physics = physics
}
}
class Chemistry: Subjects {
var equations: String
init(physics: String, equations: String) {
self.equations = equations
super.init(physics: physics)
}
}
class Maths: Subjects {
var formulae: String
init(physics: String, formulae: String) {
self.formulae = formulae
super.init(physics: physics)
}
}
let sa = [
Chemistry(physics: "solid physics", equations: "Hertz"),
Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
Chemistry(physics: "Thermo physics", equations: "Decibels"),
Maths(physics: "Astro Physics", formulae: "MegaHertz"),
Maths(physics: "Differential Equations", formulae: "Cosine Series")]
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")
var chemCount = 0
var mathsCount = 0
for item in sa {
if item is Chemistry {
++chemCount
} else if item is Maths {
++mathsCount
}
}
print("Subjects in chemistry contains \(chemCount) topics and maths contains \(mathsCount) topics")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Subjects in chemistry contains 2 topics and maths contains 3 topics
Hạ cấp
Việc hạ cấp kiểu lớp con có thể được thực hiện bằng hai toán tử (as? Và as!). 'As?' trả về một giá trị tùy chọn khi giá trị trả về nil. Nó được sử dụng để kiểm tra downcast thành công.
'như!' trả về lực mở như đã thảo luận trong chuỗi tùy chọn khi dự báo xuống trả về giá trị nil. Nó được sử dụng để kích hoạt lỗi thời gian chạy trong trường hợp downcast thất bại
class Subjects {
var physics: String
init(physics: String) {
self.physics = physics
}
}
class Chemistry: Subjects {
var equations: String
init(physics: String, equations: String) {
self.equations = equations
super.init(physics: physics)
}
}
class Maths: Subjects {
var formulae: String
init(physics: String, formulae: String) {
self.formulae = formulae
super.init(physics: physics)
}
}
let sa = [
Chemistry(physics: "solid physics", equations: "Hertz"),
Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
Chemistry(physics: "Thermo physics", equations: "Decibels"),
Maths(physics: "Astro Physics", formulae: "MegaHertz"),
Maths(physics: "Differential Equations", formulae: "Cosine Series")]
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")
var chemCount = 0
var mathsCount = 0
for item in sa {
if let print = item as? Chemistry {
print("Chemistry topics are: '\(print.physics)', \(print.equations)")
} else if let example = item as? Maths {
print("Maths topics are: '\(example.physics)', \(example.formulae)")
}
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Chemistry topics are: 'solid physics', Hertz
Maths topics are: 'Fluid Dynamics', Giga Hertz
Chemistry topics are: 'Thermo physics', Decibels
Maths topics are: 'Astro Physics', MegaHertz
Maths topics are: 'Differential Equations', Cosine Series
Đánh máy: Bất kỳ và Bất kỳ Đối tượng nào
Từ khóa 'Bất kỳ' được sử dụng để đại diện cho một phiên bản thuộc về bất kỳ kiểu nào bao gồm các kiểu hàm.
class Subjects {
var physics: String
init(physics: String) {
self.physics = physics
}
}
class Chemistry: Subjects {
var equations: String
init(physics: String, equations: String) {
self.equations = equations
super.init(physics: physics)
}
}
class Maths: Subjects {
var formulae: String
init(physics: String, formulae: String) {
self.formulae = formulae
super.init(physics: physics)
}
}
let sa = [
Chemistry(physics: "solid physics", equations: "Hertz"),
Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
Chemistry(physics: "Thermo physics", equations: "Decibels"),
Maths(physics: "Astro Physics", formulae: "MegaHertz"),
Maths(physics: "Differential Equations", formulae: "Cosine Series")]
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")
var chemCount = 0
var mathsCount = 0
for item in sa {
if let print = item as? Chemistry {
print("Chemistry topics are: '\(print.physics)', \(print.equations)")
} else if let example = item as? Maths {
print("Maths topics are: '\(example.physics)', \(example.formulae)")
}
}
var exampleany = [Any]()
exampleany.append(12)
exampleany.append(3.14159)
exampleany.append("Example for Any")
exampleany.append(Chemistry(physics: "solid physics", equations: "Hertz"))
for print in exampleany {
switch print {
case let someInt as Int:
print("Integer value is \(someInt)")
case let someDouble as Double where someDouble > 0:
print("Pi value is \(someDouble)")
case let someString as String:
print("\(someString)")
case let phy as Chemistry:
print("Topics '\(phy.physics)', \(phy.equations)")
default:
print("None")
}
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Chemistry topics are: 'solid physics', Hertz
Maths topics are: 'Fluid Dynamics', Giga Hertz
Chemistry topics are: 'Thermo physics', Decibels
Maths topics are: 'Astro Physics', MegaHertz
Maths topics are: 'Differential Equations', Cosine Series
Integer value is 12
Pi value is 3.14159
Example for Any
Topics 'solid physics', Hertz
AnyObject
Để thể hiện trường hợp của bất kỳ loại lớp nào, từ khóa 'AnyObject' được sử dụng.
class Subjects {
var physics: String
init(physics: String) {
self.physics = physics
}
}
class Chemistry: Subjects {
var equations: String
init(physics: String, equations: String) {
self.equations = equations
super.init(physics: physics)
}
}
class Maths: Subjects {
var formulae: String
init(physics: String, formulae: String) {
self.formulae = formulae
super.init(physics: physics)
}
}
let saprint: [AnyObject] = [Chemistry(physics: "solid physics", equations: "Hertz"),
Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
Chemistry(physics: "Thermo physics", equations: "Decibels"),
Maths(physics: "Astro Physics", formulae: "MegaHertz"),
Maths(physics: "Differential Equations", formulae: "Cosine Series")]
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")
var chemCount = 0
var mathsCount = 0
for item in saprint {
if let print = item as? Chemistry {
print("Chemistry topics are: '\(print.physics)', \(print.equations)")
} else if let example = item as? Maths {
print("Maths topics are: '\(example.physics)', \(example.formulae)")
}
}
var exampleany = [Any]()
exampleany.append(12)
exampleany.append(3.14159)
exampleany.append("Example for Any")
exampleany.append(Chemistry(physics: "solid physics", equations: "Hertz"))
for print in exampleany {
switch print {
case let someInt as Int:
print("Integer value is \(someInt)")
case let someDouble as Double where someDouble > 0:
print("Pi value is \(someDouble)")
case let someString as String:
print("\(someString)")
case let phy as Chemistry:
print("Topics '\(phy.physics)', \(phy.equations)")
default:
print("None")
}
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Chemistry topics are: 'solid physics', Hertz
Maths topics are: 'Fluid Dynamics', Giga Hertz
Chemistry topics are: 'Thermo physics', Decibels
Maths topics are: 'Astro Physics', MegaHertz
Maths topics are: 'Differential Equations', Cosine Series
Integer value is 12
Pi value is 3.14159
Example for Any
Topics 'solid physics', Hertz
Chức năng của một lớp, cấu trúc hoặc kiểu liệt kê hiện có có thể được thêm vào với sự trợ giúp của các phần mở rộng. Chức năng loại có thể được thêm vào bằng các tiện ích mở rộng nhưng không thể ghi đè chức năng với các tiện ích mở rộng.
Swift Extension Functionalities -
- Thêm thuộc tính được tính toán và thuộc tính kiểu được tính toán
- Định nghĩa phương thức thể hiện và kiểu.
- Cung cấp bộ khởi tạo mới.
- Xác định chỉ số phụ
- Định nghĩa và sử dụng các kiểu lồng nhau mới
- Làm cho một loại hiện có tuân theo một giao thức
Các tiện ích mở rộng được khai báo với từ khóa 'tiện ích mở rộng'
Cú pháp
extension SomeType {
// new functionality can be added here
}
Kiểu hiện tại cũng có thể được thêm vào với các phần mở rộng để làm cho nó trở thành một tiêu chuẩn giao thức và cú pháp của nó tương tự như cú pháp của các lớp hoặc cấu trúc.
extension SomeType: SomeProtocol, AnotherProtocol {
// protocol requirements is described here
}
Thuộc tính tính toán
Các thuộc tính 'instance' và 'type' được tính toán cũng có thể được mở rộng với sự trợ giúp của các phần mở rộng.
extension Int {
var add: Int {return self + 100 }
var sub: Int { return self - 10 }
var mul: Int { return self * 10 }
var div: Int { return self / 5 }
}
let addition = 3.add
print("Addition is \(addition)")
let subtraction = 120.sub
print("Subtraction is \(subtraction)")
let multiplication = 39.mul
print("Multiplication is \(multiplication)")
let division = 55.div
print("Division is \(division)")
let mix = 30.add + 34.sub
print("Mixed Type is \(mix)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Addition is 103
Subtraction is 110
Multiplication is 390
Division is 11
Mixed Type is 154
Khởi tạo
Swift 4 cung cấp sự linh hoạt để thêm các trình khởi tạo mới vào một kiểu hiện có bằng các phần mở rộng. Người dùng có thể thêm các loại tùy chỉnh của riêng họ để mở rộng các loại đã được xác định và các tùy chọn khởi tạo bổ sung cũng có thể thực hiện được. Phần mở rộng chỉ hỗ trợ init (). deinit () không được hỗ trợ bởi các phần mở rộng.
struct sum {
var num1 = 100, num2 = 200
}
struct diff {
var no1 = 200, no2 = 100
}
struct mult {
var a = sum()
var b = diff()
}
let calc = mult()
print ("Inside mult block \(calc.a.num1, calc.a.num2)")
print("Inside mult block \(calc.b.no1, calc.b.no2)")
let memcalc = mult(a: sum(num1: 300, num2: 500),b: diff(no1: 300, no2: 100))
print("Inside mult block \(memcalc.a.num1, memcalc.a.num2)")
print("Inside mult block \(memcalc.b.no1, memcalc.b.no2)")
extension mult {
init(x: sum, y: diff) {
let X = x.num1 + x.num2
let Y = y.no1 + y.no2
}
}
let a = sum(num1: 100, num2: 200)
print("Inside Sum Block:\( a.num1, a.num2)")
let b = diff(no1: 200, no2: 100)
print("Inside Diff Block: \(b.no1, b.no2)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Inside mult block (100, 200)
Inside mult block (200, 100)
Inside mult block (300, 500)
Inside mult block (300, 100)
Inside Sum Block:(100, 200)
Inside Diff Block: (200, 100)
Phương pháp
Các phương thức phiên bản mới và các phương thức kiểu có thể được thêm vào lớp con với sự trợ giúp của các phần mở rộng.
extension Int {
func topics(summation: () -> ()) {
for _ in 0..<self {
summation()
}
}
}
4.topics(summation: {
print("Inside Extensions Block")
})
3.topics(summation: {
print("Inside Type Casting Block")
})
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Inside Extensions Block
Inside Extensions Block
Inside Extensions Block
Inside Extensions Block
Inside Type Casting Block
Inside Type Casting Block
Inside Type Casting Block
Hàm topic () nhận đối số kiểu '(tổng kết: () → ())' để cho biết hàm không nhận bất kỳ đối số nào và nó sẽ không trả về bất kỳ giá trị nào. Để gọi hàm đó nhiều lần, khối for được khởi tạo và lệnh gọi phương thức có topic () được khởi tạo.
Phương pháp đột biến
Các phương thức phiên bản cũng có thể bị thay đổi khi được khai báo là phần mở rộng.
Các phương thức cấu trúc và liệt kê sửa đổi bản thân hoặc các thuộc tính của nó phải đánh dấu phương thức thể hiện là thay đổi, giống như phương thức thay đổi từ một triển khai ban đầu.
extension Double {
mutating func square() {
let pi = 3.1415
self = pi * self * self
}
}
var Trial1 = 3.3
Trial1.square()
print("Area of circle is: \(Trial1)")
var Trial2 = 5.8
Trial2.square()
print("Area of circle is: \(Trial2)")
var Trial3 = 120.3
Trial3.square()
print("Area of circle is: \(Trial3)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Area of circle is: 34.210935
Area of circle is: 105.68006
Area of circle is: 45464.070735
Đăng ký
Bạn cũng có thể thêm các chỉ số mới vào các phiên bản đã được khai báo bằng các tiện ích mở rộng.
extension Int {
subscript(var multtable: Int) -> Int {
var no1 = 1
while multtable > 0 {
no1 *= 10
--multtable
}
return (self / no1) % 10
}
}
print(12[0])
print(7869[1])
print(786543[2])
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
2
6
5
Các loại lồng nhau
Các kiểu lồng nhau cho các thể hiện lớp, cấu trúc và kiểu liệt kê cũng có thể được mở rộng với sự trợ giúp của các phần mở rộng.
extension Int {
enum calc {
case add
case sub
case mult
case div
case anything
}
var print: calc {
switch self {
case 0:
return .add
case 1:
return .sub
case 2:
return .mult
case 3:
return .div
default:
return .anything
}
}
}
func result(numb: [Int]) {
for i in numb {
switch i.print {
case .add:
print(" 10 ")
case .sub:
print(" 20 ")
case .mult:
print(" 30 ")
case .div:
print(" 40 ")
default:
print(" 50 ")
}
}
}
result(numb: [0, 1, 2, 3, 4, 7])
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
10
20
30
40
50
50
Các giao thức cung cấp bản thiết kế cho các Phương thức, thuộc tính và các chức năng yêu cầu khác. Nó chỉ được mô tả như một phương thức hoặc khung thuộc tính thay vì thực thi. Việc triển khai các phương thức và thuộc tính có thể được thực hiện nhiều hơn nữa bằng cách xác định các lớp, chức năng và kiểu liệt kê. Sự phù hợp của một giao thức được định nghĩa là các phương thức hoặc thuộc tính thỏa mãn các yêu cầu của giao thức.
Cú pháp
Các giao thức cũng tuân theo cú pháp tương tự như của các lớp, cấu trúc và kiểu liệt kê -
protocol SomeProtocol {
// protocol definition
}
Các giao thức được khai báo sau tên lớp, cấu trúc hoặc kiểu liệt kê. Cũng có thể khai báo một giao thức và nhiều giao thức. Nếu nhiều giao thức được xác định, chúng phải được phân tách bằng dấu phẩy.
struct SomeStructure: Protocol1, Protocol2 {
// structure definition
}
Khi một giao thức phải được xác định cho siêu lớp, tên giao thức phải theo sau tên siêu lớp với dấu phẩy.
class SomeClass: SomeSuperclass, Protocol1, Protocol2 {
// class definition
}
Yêu cầu về tài sản và phương pháp
Giao thức được sử dụng để chỉ định thuộc tính loại lớp cụ thể hoặc thuộc tính thể hiện. Nó chỉ chỉ định loại hoặc thuộc tính cá thể một mình thay vì chỉ định đó là thuộc tính được lưu trữ hay tính toán. Ngoài ra, nó được sử dụng để chỉ định xem thuộc tính là 'gettable' hay 'có thể thiết lập được'.
Các yêu cầu thuộc tính được khai báo bởi từ khóa 'var' dưới dạng các biến thuộc tính. {get set} được sử dụng để khai báo các thuộc tính gettable và có thể thiết lập sau khi khai báo kiểu của chúng. Gettable được thuộc tính {get} đề cập sau phần khai báo kiểu của chúng.
protocol classa {
var marks: Int { get set }
var result: Bool { get }
func attendance() -> String
func markssecured() -> String
}
protocol classb: classa {
var present: Bool { get set }
var subject: String { get set }
var stname: String { get set }
}
class classc: classb {
var marks = 96
let result = true
var present = false
var subject = "Swift 4 Protocols"
var stname = "Protocols"
func attendance() -> String {
return "The \(stname) has secured 99% attendance"
}
func markssecured() -> String {
return "\(stname) has scored \(marks)"
}
}
let studdet = classc()
studdet.stname = "Swift 4"
studdet.marks = 98
studdet.markssecured()
print(studdet.marks)
print(studdet.result)
print(studdet.present)
print(studdet.subject)
print(studdet.stname)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
98
true
false
Swift 4 Protocols
Swift 4
Yêu cầu về phương pháp đột biến
protocol daysofaweek {
mutating func print()
}
enum days: daysofaweek {
case sun, mon, tue, wed, thurs, fri, sat
mutating func print() {
switch self {
case sun:
self = sun
print("Sunday")
case mon:
self = mon
print("Monday")
case tue:
self = tue
print("Tuesday")
case wed:
self = wed
print("Wednesday")
case mon:
self = thurs
print("Thursday")
case tue:
self = fri
print("Friday")
case sat:
self = sat
print("Saturday")
default:
print("NO Such Day")
}
}
}
var res = days.wed
res.print()
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Wednesday
Yêu cầu về trình khởi tạo
Swing cho phép người dùng khởi tạo các giao thức để tuân theo kiểu tương tự như của các trình khởi tạo thông thường.
Cú pháp
protocol SomeProtocol {
init(someParameter: Int)
}
Ví dụ
protocol tcpprotocol {
init(aprot: Int)
}
Triển khai lớp các yêu cầu của bộ khởi tạo giao thức
Bộ khởi tạo được chỉ định hoặc tiện lợi cho phép người dùng khởi tạo một giao thức để phù hợp với tiêu chuẩn của nó bằng từ khóa 'bắt buộc' dành riêng.
class SomeClass: SomeProtocol {
required init(someParameter: Int) {
// initializer implementation statements
}
}
protocol tcpprotocol {
init(aprot: Int)
}
class tcpClass: tcpprotocol {
required init(aprot: Int) {
}
}
Sự tuân thủ giao thức được đảm bảo trên tất cả các lớp con để triển khai rõ ràng hoặc kế thừa bởi công cụ sửa đổi 'bắt buộc'.
Khi một lớp con ghi đè yêu cầu khởi tạo siêu lớp của nó, nó được chỉ định bởi từ khóa bổ trợ 'ghi đè'.
protocol tcpprotocol {
init(no1: Int)
}
class mainClass {
var no1: Int // local storage
init(no1: Int) {
self.no1 = no1 // initialization
}
}
class subClass: mainClass, tcpprotocol {
var no2: Int
init(no1: Int, no2 : Int) {
self.no2 = no2
super.init(no1:no1)
}
// Requires only one parameter for convenient method
required override convenience init(no1: Int) {
self.init(no1:no1, no2:0)
}
}
let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
res is: 20
res is: 30
res is: 50
Giao thức dưới dạng các loại
Thay vì triển khai các chức năng trong một giao thức, chúng được sử dụng làm kiểu cho các hàm, lớp, phương thức, v.v.
Các giao thức có thể được truy cập dưới dạng các loại trong -
Hàm, phương thức hoặc khởi tạo dưới dạng tham số hoặc kiểu trả về
Hằng số, biến hoặc thuộc tính
Mảng, từ điển hoặc các vùng chứa khác dưới dạng các mục
protocol Generator {
typealias members
func next() -> members?
}
var items = [10,20,30].generate()
while let x = items.next() {
print(x)
}
for lists in map([1,2,3], {i in i*5}) {
print(lists)
}
print([100,200,300])
print(map([1,2,3], {i in i*10}))
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
10
20
30
5
10
15
[100, 200, 300]
[10, 20, 30]
Thêm sự tuân thủ giao thức với một phần mở rộng
Loại hiện tại có thể được chấp nhận và tuân theo một giao thức mới bằng cách sử dụng các tiện ích mở rộng. Các thuộc tính, phương pháp và chỉ số phụ mới có thể được thêm vào các loại hiện có với sự trợ giúp của tiện ích mở rộng.
protocol AgeClasificationProtocol {
var age: Int { get }
func agetype() -> String
}
class Person {
let firstname: String
let lastname: String
var age: Int
init(firstname: String, lastname: String) {
self.firstname = firstname
self.lastname = lastname
self.age = 10
}
}
extension Person : AgeClasificationProtocol {
func fullname() -> String {
var c: String
c = firstname + " " + lastname
return c
}
func agetype() -> String {
switch age {
case 0...2:
return "Baby"
case 2...12:
return "Child"
case 13...19:
return "Teenager"
case let x where x > 65:
return "Elderly"
default:
return "Normal"
}
}
}
Kế thừa giao thức
Swift 4 cho phép các giao thức kế thừa các thuộc tính từ các thuộc tính đã xác định của nó. Nó tương tự như kế thừa lớp, nhưng với sự lựa chọn liệt kê nhiều giao thức kế thừa được phân tách bằng dấu phẩy.
protocol classa {
var no1: Int { get set }
func calc(sum: Int)
}
protocol result {
func print(target: classa)
}
class student2: result {
func print(target: classa) {
target.calc(sum: 1)
}
}
class classb: result {
func print(target: classa) {
target.calc(sum: 5)
}
}
class student: classa {
var no1: Int = 10
func calc(sum: Int) {
no1 -= sum
print("Student attempted \(sum) times to pass")
if no1 <= 0 {
print("Student is absent for exam")
}
}
}
class Player {
var stmark: result!
init(stmark: result) {
self.stmark = stmark
}
func print(target: classa) {
stmark.print(target: target)
}
}
var marks = Player(stmark: student2())
var marksec = student()
marks.print(target: marksec)
marks.print(target: marksec)
marks.print(target: marksec)
marks.stmark = classb()
marks.print(target: marksec)
marks.print(target: marksec)
marks.print(target: marksec)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Student attempted 1 times to pass
Student attempted 1 times to pass
Student attempted 1 times to pass
Student attempted 5 times to pass
Student attempted 5 times to pass
Student is absent for exam
Student attempted 5 times to pass
Student is absent for exam
Giao thức chỉ lớp học
Khi các giao thức được định nghĩa và người dùng muốn định nghĩa giao thức với các lớp, nó nên được thêm vào bằng cách xác định lớp trước, sau đó là danh sách kế thừa của giao thức.
protocol tcpprotocol {
init(no1: Int)
}
class mainClass {
var no1: Int // local storage
init(no1: Int) {
self.no1 = no1 // initialization
}
}
class subClass: mainClass, tcpprotocol {
var no2: Int
init(no1: Int, no2 : Int) {
self.no2 = no2
super.init(no1:no1)
}
// Requires only one parameter for convenient method
required override convenience init(no1: Int) {
self.init(no1:no1, no2:0)
}
}
let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
res is: 20
res is: 30
res is: 50
Thành phần giao thức
Swift 4 cho phép nhiều giao thức được gọi cùng một lúc với sự trợ giúp của thành phần giao thức.
Cú pháp
protocol<SomeProtocol, AnotherProtocol>
Thí dụ
protocol stname {
var name: String { get }
}
protocol stage {
var age: Int { get }
}
struct Person: stname, stage {
var name: String
var age: Int
}
func print(celebrator: stname & stage) {
print("\(celebrator.name) is \(celebrator.age) years old")
}
let studname = Person(name: "Priya", age: 21)
print(studname)
let stud = Person(name: "Rehan", age: 29)
print(stud)
let student = Person(name: "Roshan", age: 19)
print(student)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Person(name: "Priya", age: 21)
Person(name: "Rehan", age: 29)
Person(name: "Roshan", age: 19)
Kiểm tra sự tuân thủ giao thức
Sự phù hợp của giao thức được kiểm tra bởi các toán tử 'is' và 'as' tương tự như của kiểu đúc.
Toán tử is trả về true nếu một thể hiện tuân theo tiêu chuẩn giao thức và trả về false nếu nó không thành công.
Các as? phiên bản của toán tử downcast trả về một giá trị tùy chọn của kiểu giao thức và giá trị này là 0 nếu phiên bản không tuân theo giao thức đó.
Phiên bản as của toán tử downcast buộc downcast đến loại giao thức và gây ra lỗi thời gian chạy nếu downcast không thành công.
import Foundation
@objc protocol rectangle {
var area: Double { get }
}
@objc class Circle: rectangle {
let pi = 3.1415927
var radius: Double
var area: Double { return pi * radius * radius }
init(radius: Double) { self.radius = radius }
}
@objc class result: rectangle {
var area: Double
init(area: Double) { self.area = area }
}
class sides {
var rectsides: Int
init(rectsides: Int) { self.rectsides = rectsides }
}
let objects: [AnyObject] = [Circle(radius: 2.0),result(area:198),sides(rectsides: 4)]
for object in objects {
if let objectWithArea = object as? rectangle {
print("Area is \(objectWithArea.area)")
} else {
print("Rectangle area is not defined")
}
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Area is 12.5663708
Area is 198.0
Rectangle area is not defined
Ngôn ngữ Swift 4 cung cấp các tính năng 'Chung' để viết các hàm và kiểu linh hoạt và có thể tái sử dụng. Generics được sử dụng để tránh trùng lặp và cung cấp tính trừu tượng. Thư viện tiêu chuẩn của Swift 4 được xây dựng bằng mã chung. Loại 'Mảng' và 'Từ điển' của Swift 4s thuộc về các bộ sưu tập chung. Với sự trợ giúp của mảng và từ điển, các mảng được xác định để chứa các giá trị 'Int' và giá trị 'Chuỗi' hoặc bất kỳ kiểu nào khác.
func exchange(a: inout Int, b: inout Int) {
let temp = a
a = b
b = temp
}
var numb1 = 100
var numb2 = 200
print("Before Swapping values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping values are: \(numb1) and \(numb2)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Before Swapping values are: 100 and 200
After Swapping values are: 200 and 100
Chức năng chung: Tham số kiểu
Các hàm chung có thể được sử dụng để truy cập bất kỳ kiểu dữ liệu nào như 'Int' hoặc 'Chuỗi'.
func exchange<T>(a: inout T, b: inout T) {
let temp = a
a = b
b = temp
}
var numb1 = 100
var numb2 = 200
print("Before Swapping Int values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping Int values are: \(numb1) and \(numb2)")
var str1 = "Generics"
var str2 = "Functions"
print("Before Swapping String values are: \(str1) and \(str2)")
exchange(a: &str1, b: &str2)
print("After Swapping String values are: \(str1) and \(str2)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Before Swapping Int values are: 100 and 200
After Swapping Int values are: 200 and 100
Before Swapping String values are: Generics and Functions
After Swapping String values are: Functions and Generics
Hàm Exchange () được sử dụng để hoán đổi các giá trị được mô tả trong chương trình trên và <T> được sử dụng như một tham số kiểu. Lần đầu tiên, hàm Exchange () được gọi để trả về giá trị 'Int' và lần gọi thứ hai tới hàm Exchange () sẽ trả về giá trị 'Chuỗi'. Nhiều loại tham số có thể được đưa vào bên trong dấu ngoặc nhọn được phân tách bằng dấu phẩy.
Tham số kiểu được đặt tên do người dùng định nghĩa để biết mục đích của tham số kiểu mà nó nắm giữ. Swift 4 cung cấp <T> dưới dạng tên tham số kiểu chung. Tuy nhiên, các tham số kiểu như Mảng và Từ điển cũng có thể được đặt tên là khóa, giá trị để xác định rằng chúng thuộc kiểu 'Từ điển'.
struct TOS<T> {
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Type Parameters")
print(tos.items)
tos.push(item: "Naming Type Parameters")
print(tos.items)
let deletetos = tos.pop()
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]
Mở rộng một loại chung
Mở rộng thuộc tính ngăn xếp để biết đầu mục được bao gồm từ khóa 'mở rộng'.
struct TOS<T> {
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Type Parameters")
print(tos.items)
tos.push(item: "Naming Type Parameters")
print(tos.items)
extension TOS {
var first: T? {
return items.isEmpty ? nil : items[items.count - 1]
}
}
if let first = tos.first {
print("The top item on the stack is \(first).")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
["Swift 4"]
["Swift 4", "Generics"]
["Swift 4", "Generics", "Type Parameters"]
["Swift 4", "Generics", "Type Parameters", "Naming Type Parameters"]
The top item on the stack is Naming Type Parameters.
Loại Ràng buộc
Ngôn ngữ Swift 4 cho phép 'các ràng buộc kiểu' xác định xem tham số kiểu kế thừa từ một lớp cụ thể hay để đảm bảo tiêu chuẩn tuân thủ giao thức.
func exchange<T>(a: inout T, b: inout T) {
let temp = a
a = b
b = temp
}
var numb1 = 100
var numb2 = 200
print("Before Swapping Int values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping Int values are: \(numb1) and \(numb2)")
var str1 = "Generics"
var str2 = "Functions"
print("Before Swapping String values are: \(str1) and \(str2)")
exchange(a: &str1, b: &str2)
print("After Swapping String values are: \(str1) and \(str2)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Before Swapping Int values are: 100 and 200
After Swapping Int values are: 200 and 100
Before Swapping String values are: Generics and Functions
After Swapping String values are: Functions and Generics
Các loại liên kết
Swift 4 cho phép các kiểu liên kết được khai báo bên trong định nghĩa giao thức bằng từ khóa 'kiểu liên kết'.
protocol Container {
associatedtype ItemType
mutating func append(item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}
struct TOS<T>: Container {
// original Stack<T> implementation
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
// conformance to the Container protocol
mutating func append(item: T) {
self.push(item: item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> T {
return items[i]
}
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Type Parameters")
print(tos.items)
tos.push(item: "Naming Type Parameters")
print(tos.items)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]
Điều khoản ở đâu
Các ràng buộc kiểu cho phép người dùng xác định các yêu cầu về các tham số kiểu được liên kết với một chức năng hoặc kiểu chung. Để xác định các yêu cầu cho các kiểu liên kết, mệnh đề 'where' được khai báo như một phần của danh sách tham số kiểu. Từ khóa 'where' được đặt ngay sau danh sách các tham số kiểu, theo sau là các ràng buộc của các kiểu liên kết, mối quan hệ bình đẳng giữa các kiểu và các kiểu liên kết.
protocol Container {
associatedtype ItemType
mutating func append(item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}
struct Stack<T>: Container {
// original Stack<T> implementation
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
// conformance to the Container protocol
mutating func append(item: T) {
self.push(item: item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> T {
return items[i]
}
}
func allItemsMatch<
C1: Container, C2: Container
where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
(someContainer: C1, anotherContainer: C2) -> Bool {
// check that both containers contain the same number of items
if someContainer.count != anotherContainer.count {
return false
}
// check each pair of items to see if they are equivalent
for i in 0..<someContainer.count {
if someContainer[i] != anotherContainer[i] {
return false
}
}
// all items match, so return true
return true
}
var tos = Stack<String>()
tos.push(item: "Swift 4")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Where Clause")
print(tos.items)
var eos = ["Swift 4", "Generics", "Where Clause"]
print(eos)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Where Clause]
[Swift 4, Generics, Where Clause]
Để hạn chế quyền truy cập vào các khối mã, các mô-đun và sự trừu tượng hóa được thực hiện thông qua kiểm soát truy cập. Các lớp, cấu trúc và bảng liệt kê có thể được truy cập theo thuộc tính, phương thức, bộ khởi tạo và chỉ số con của chúng bằng cơ chế kiểm soát truy cập. Hằng số, biến và hàm trong một giao thức bị hạn chế và được phép truy cập như toàn cục và cục bộ thông qua kiểm soát truy cập. Kiểm soát truy cập áp dụng cho các thuộc tính, loại và chức năng có thể được gọi là 'thực thể'.
Mô hình kiểm soát truy cập dựa trên mô-đun và tệp nguồn.
Mô-đun được định nghĩa là một đơn vị phân phối mã duy nhất và có thể được nhập bằng từ khóa 'nhập'. Tệp nguồn được định nghĩa là một tệp mã nguồn duy nhất có trong một mô-đun để truy cập nhiều loại và chức năng.
Ngôn ngữ Swift 4 cung cấp ba cấp độ truy cập khác nhau. Đó là quyền truy cập Công khai, Nội bộ và Riêng tư.
S.Không | Cấp độ Truy cập & Định nghĩa |
---|---|
1 | Public Cho phép các thực thể được xử lý với bất kỳ tệp nguồn nào từ mô-đun xác định của chúng, tệp nguồn từ mô-đun khác nhập mô-đun xác định. |
2 | Internal Cho phép các thực thể được sử dụng trong bất kỳ tệp nguồn nào từ mô-đun xác định của chúng, nhưng không cho phép trong bất kỳ tệp nguồn nào bên ngoài mô-đun đó. |
3 | Private Hạn chế việc sử dụng một thực thể đối với tệp nguồn xác định của chính nó. Quyền truy cập riêng tư đóng vai trò để ẩn các chi tiết triển khai của một chức năng mã cụ thể. |
Cú pháp
public class SomePublicClass {}
internal class SomeInternalClass {}
private class SomePrivateClass {}
public var somePublicVariable = 0
internal let someInternalConstant = 0
private func somePrivateFunction() {}
Kiểm soát truy cập cho các loại chức năng
Một số hàm có thể có các đối số được khai báo bên trong hàm mà không có bất kỳ giá trị trả về nào. Chương trình sau đây khai báo a và b là các đối số của hàm sum (). Bên trong hàm, các giá trị cho các đối số a và b được chuyển bằng cách gọi hàm sum () và các giá trị của nó được in ra do đó loại bỏ các giá trị trả về. Để đặt kiểu trả về của hàm là riêng tư, hãy khai báo mức truy cập tổng thể của hàm bằng công cụ sửa đổi riêng.
private func sum(a: Int, b: Int) {
let a = a + b
let b = a - b
print(a, b)
}
sum(a: 20, b: 10)
sum(a: 40, b: 10)
sum(a: 24, b: 6)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
30 20
50 40
30 24
Kiểm soát truy cập cho các kiểu liệt kê
public enum Student {
case Name(String)
case Mark(Int,Int,Int)
}
var studDetails = Student.Name("Swift 4")
var studMarks = Student.Mark(98,97,95)
switch studMarks {
case .Name(let studName):
print("Student name is: \(studName).")
case .Mark(let Mark1, let Mark2, let Mark3):
print("Student Marks are: \(Mark1),\(Mark2),\(Mark3).")
}
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Student Marks are: 98,97,95
Liệt kê trong ngôn ngữ Swift 4 tự động nhận cùng một cấp độ truy cập cho các trường hợp liệt kê riêng lẻ. Hãy xem xét ví dụ để truy cập tên sinh viên và các dấu được bảo mật trong ba môn học, tên liệt kê được khai báo là sinh viên và các thành viên có mặt trong lớp enum là tên thuộc kiểu dữ liệu chuỗi, các dấu được biểu diễn dưới dạng mark1, mark2 và mark3 của kiểu dữ liệu Integer. Để truy cập tên học sinh hoặc điểm họ đã ghi. Bây giờ, trường hợp chuyển đổi sẽ in tên học sinh nếu khối trường hợp đó được thực thi nếu không, nó sẽ in các dấu được bảo mật bởi học sinh. Nếu cả hai điều kiện không thành công, khối mặc định sẽ được thực thi.
Kiểm soát truy cập cho các lớp con
Swift 4 cho phép người dùng phân lớp bất kỳ lớp nào có thể được truy cập trong bối cảnh truy cập hiện tại. Một lớp con không thể có mức truy cập cao hơn lớp cha của nó. Người dùng bị hạn chế viết một lớp con công khai của lớp cha bên trong.
public class cricket {
internal func printIt() {
print("Welcome to Swift 4 Super Class")
}
}
internal class tennis: cricket {
override internal func printIt() {
print("Welcome to Swift 4 Sub Class")
}
}
let cricinstance = cricket()
cricinstance.printIt()
let tennisinstance = tennis()
tennisinstance.printIt()
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Welcome to Swift Super Class
Welcome to Swift Sub Class
Kiểm soát truy cập cho Hằng số, biến, thuộc tính và chỉ số con
Không thể định nghĩa hằng số, biến hoặc thuộc tính Swift 4 là public hơn kiểu của nó. Việc ghi tài sản công cộng với kiểu tài sản riêng là không hợp lệ. Tương tự, một chỉ số con không thể công khai hơn chỉ mục hoặc kiểu trả về của nó.
Khi một hằng số, biến, thuộc tính hoặc chỉ số con sử dụng kiểu private, thì hằng số, biến, thuộc tính hoặc chỉ số con cũng phải được đánh dấu là private -
private var privateInstance = SomePrivateClass()
Người nhận và Người định cư
Getters và setters cho hằng số, biến, thuộc tính và chỉ số con tự động nhận cùng mức truy cập như hằng số, biến, thuộc tính hoặc chỉ số con mà chúng thuộc về.
class Samplepgm {
var counter: Int = 0{
willSet(newTotal) {
print("Total Counter is: \(newTotal)")
}
didSet {
if counter > oldValue {
print("Newly Added Counter \(counter - oldValue)")
}
}
}
}
let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700
Kiểm soát truy cập cho Trình khởi tạo và Trình khởi tạo mặc định
Trình khởi tạo tùy chỉnh có thể được chỉ định cấp truy cập nhỏ hơn hoặc bằng loại mà chúng khởi tạo. Trình khởi tạo bắt buộc phải có cùng mức truy cập với lớp mà nó thuộc về. Các loại tham số của trình khởi tạo không được riêng tư hơn cấp truy cập của chính trình khởi tạo.
Để khai báo từng và mọi lớp con của từ khóa khởi tạo 'bắt buộc' cần phải được xác định trước hàm init ().
class classA {
required init() {
let a = 10
print(a)
}
}
class classB: classA {
required init() {
let b = 30
print(b)
}
}
let res = classA()
let print = classB()
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
10
30
10
Trình khởi tạo mặc định có cùng mức truy cập với kiểu mà nó khởi tạo, trừ khi kiểu đó được định nghĩa là công khai. Khi khởi tạo mặc định được xác định là công khai, nó được coi là nội bộ. Khi người dùng cần một kiểu công khai có thể khởi tạo được bằng bộ khởi tạo không đối số trong một mô-đun khác, hãy cung cấp rõ ràng một bộ khởi tạo không đối số công khai như một phần của định nghĩa của kiểu.
Kiểm soát truy cập cho các giao thức
Khi chúng ta xác định một giao thức mới để kế thừa các chức năng từ một giao thức hiện có, cả hai đều phải được khai báo các mức truy cập giống nhau để kế thừa các thuộc tính của nhau. Kiểm soát truy cập Swift 4 sẽ không cho phép người dùng xác định giao thức 'công khai' kế thừa từ giao thức 'nội bộ'.
public protocol tcpprotocol {
init(no1: Int)
}
public class mainClass {
var no1: Int // local storage
init(no1: Int) {
self.no1 = no1 // initialization
}
}
class subClass: mainClass, tcpprotocol {
var no2: Int
init(no1: Int, no2 : Int) {
self.no2 = no2
super.init(no1:no1)
}
// Requires only one parameter for convenient method
required override convenience init(no1: Int) {
self.init(no1:no1, no2:0)
}
}
let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
res is: 20
res is: 30
res is: 50
Kiểm soát truy cập cho các tiện ích mở rộng
Swift 4 không cho phép người dùng cung cấp công cụ sửa đổi cấp độ truy cập rõ ràng cho tiện ích mở rộng khi người dùng sử dụng tiện ích mở rộng đó để thêm sự tuân thủ giao thức. Mức truy cập mặc định cho mỗi việc triển khai yêu cầu giao thức trong tiện ích mở rộng được cung cấp mức truy cập giao thức riêng.
Kiểm soát truy cập cho Generics
Generics cho phép người dùng chỉ định mức truy cập tối thiểu để truy cập các ràng buộc kiểu trên các tham số kiểu của nó.
public struct TOS<T> {
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Type Parameters")
print(tos.items)
tos.push(item: "Naming Type Parameters")
print(tos.items)
let deletetos = tos.pop()
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]
Kiểm soát truy cập cho loại bí danh
Người dùng có thể xác định bí danh loại để xử lý các loại kiểm soát truy cập riêng biệt. Người dùng có thể xác định cùng một cấp độ truy cập hoặc các cấp độ truy cập khác nhau. Khi bí danh kiểu là 'riêng tư', các thành viên liên kết của nó có thể được khai báo là 'riêng tư, nội bộ của kiểu công khai'. Khi loại bí danh là công khai, các thành viên không thể có bí danh là tên 'nội bộ' hoặc 'riêng tư'
Bất kỳ loại bí danh nào bạn xác định đều được coi là các loại riêng biệt cho mục đích kiểm soát truy cập. Bí danh kiểu có thể có cấp độ truy cập nhỏ hơn hoặc bằng cấp độ truy cập của kiểu bí danh đó. Ví dụ: bí danh kiểu riêng tư có thể bí danh là kiểu riêng tư, nội bộ hoặc công khai, nhưng bí danh kiểu công khai không thể bí danh là kiểu nội bộ hoặc riêng tư.
public protocol Container {
associatedtype ItemType
mutating func append(item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}
struct Stack<T>: Container {
// original Stack<T> implementation
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
// conformance to the Container protocol
mutating func append(item: T) {
self.push(item: item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> T {
return items[i]
}
}
func allItemsMatch<
C1: Container, C2: Container
where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
(someContainer: C1, anotherContainer: C2) -> Bool {
// check that both containers contain the same number of items
if someContainer.count != anotherContainer.count {
return false
}
// check each pair of items to see if they are equivalent
for i in 0..<someContainer.count {
if someContainer[i] != anotherContainer[i] {
return false
}
}
// all items match, so return true
return true
}
var tos = Stack<String>()
tos.push(item: "Swift 4")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Where Clause")
print(tos.items)
var eos = ["Swift 4", "Generics", "Where Clause"]
print(eos)
Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:
[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Where Clause]
[Swift 4, Generics, Where Clause]
Mã hóa và giải mã Swift
Swift 4 giới thiệu một Codable Giao thức, cho phép bạn tuần tự hóa và Hủy tuần tự hóa các loại dữ liệu tùy chỉnh mà không cần viết bất kỳ mã đặc biệt nào - và không phải lo lắng về việc mất các loại giá trị của bạn.
struct Language: Codable {
var name: String
var version: Int
}
let swift = Language(name: "Swift", version: 4)
let java = Language(name: "java", version: 8)
let R = Language(name: "R", version: 3
Lưu ý rằng Langauage đang tuân thủ Giao thức có thể mã hóa. Bây giờ chúng ta sẽ chuyển nó thành Biểu diễn dữ liệu Json bằng một dòng đơn giản.
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(java) {
//Perform some operations on this value.
}
Swift sẽ tự động mã hóa tất cả các giá trị bên trong kiểu dữ liệu của bạn.
Bạn có thể giải mã dữ liệu bằng chức năng Bộ giải mã như
let decoder = JSONDecoder()
if let decoded = try? decoder.decode(Language.self, from: encoded) {
//Perform some operations on this value.
}
Cả JSONEncoder và đối tác danh sách thuộc tính PropertyListEncoder của nó đều có rất nhiều tùy chọn để tùy chỉnh cách chúng hoạt động.