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
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 varageđể 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,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ể,NoneSome(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áoablàm đối số cho hàm sum (). bên trong chính hàm các giá trị cho các đối sốab đượ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ố no1no2 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.