Bài viết này mình sẽ trình bày những thứ cơ bản về cú pháp với Swift. Bài viết sẽ gồm các phần


  • Hằng và Biến
  • Ghi chú
  • Dấu chấm phẩy
  • Số (Integers)
  • Số thập phân (Floating number)
  • Type Safety và Type Inference
  • Cách viết số (Numeric Literals)
  • Bí danh kiểu dữ liệu (Type Aliases)
  • Kiểu Bool
  • Tuples
  • Optionals
  • Kiểm soát lỗi (Error Handling)
  • Gỡ rối (Debugging with Assertions)

Hằng và biến


 


Tương tự như đa số các ngôn ngữ lập trình khác, Swift cũng có các hằng và biến. Bên dưới là cách khai báo


 


let maxNumber = 100 // khai báo hằng

var currentNumber = 10 // khai báo biến

 


Ngoài ra, tương tự như trong C, bạn cũng có thể khai báo cùng lúc nhiều biến như sau:


 


var prevNumber = 0, currentNumber = 1, nextNumber = 2



Type Annotations


 


Khi khai báo biến, swift không yêu cầu bạn phải quy định kiểu dữ liệu, tuy nhiên bạn vẫn có thể quy định kiểu dữ liệu cho biến như sau


var welcomeMessage: String welcomeMessage = "Hello Kipalog"


Tới đây chắc hẳn bạn sẽ đặt ra 1 câu hỏi là "Nếu như đã khai báo là string, thì có gán integer được không?"
Mình nghĩ chắc bạn nên tự tay kiểm tra lấy, vì swift là một ngôn ngữ khá mới, bạn cũng nên vọc 1 chút chứ nhỉ :smile:


 


Đặt tên biến và hằng
Tên hằng và biến không được chứa khoảng trắng, kí tự đặc biệt, ..v..v.. mà chỉ bao gồm số và chữ mà thôi.
Ngoài ra, khi đã khai báo một biến, bạn không thể khai báo lại một biến trùng tên với nó. Và bạn cũng không thể chuyển từ hằng sang biến và ngược lại, từ biến sang hằng.


var welcomeMessage = "Hello" welcomeMessage = "Kipalog" // hoàn toàn hợp lệ let welcome = "Hello" welcome = "Kipalog" // lỗi, vì welcome ở đây là hằng


In biến và hằng ra màn hình
Bạn có thể dễ dàng in ra màn hình với hàm print
Ví dụ:


var welcomeMessage = "Hello Kipalog " let welcome = "I'm Pham Quoc Thang" print(welcomeMessage) print(welcome) print("Hello, \(welcome)") // output: Hello, I'm Pham Quoc Thang



Bạn có thể tham khảo thêm tại đây: Link



 


Ghi chú


 


Ví dụ:


// Ghi chú 1 dòng /* ghi chú nhiều dòng*/


Khác với ghi chú ở ngôn ngữ C, Swift cho phép các ghi chú lồng vào nhau


/* bắt đầu ghi chú nhiều dòng /* đây là dòng thứ 2 */ và đây là dòng thứ 3, kết thúc của ghi chú dòng 1*/


Dấu chấm phẩy


 


Không giống nhiều ngôn ngữ khác, ở Swift không yêu cầu dấu chấm phẩy ở cuối mỗi câu lệnh. Chắc hẳn bạn cũng đã nhận ra từ các ví dụ bên trên mà mình viết. Tuy nhiên, dấu chấm phẩy được yêu cầu phải có nếu như bạn viết 2 câu lệnh trên dùng 1 dòng.
Ví dụ:


let cat = "a cat"; print(cat) // prints "a cat"


Số (Integers)


 


Số nguyên là số không có thành phần phân đoạn (no fractional component) hay dễ hiểu là dấu chấm động hay phần thập phân giống như 23, -43
Số nguyên ở swift có signed và unsigned giống trong C.


 


  • Signed bao gồm số âm, số dương và số 0
  • Unsigned bao gồm số 0 và số dương

 


Swift cũng cung cấp kiểu dữ liệu số ở 8, 16, 32, 64 bit. Ví dụ: UInt8, Uint32


 


Max và Min
Bạn có thể truy xuất số lớn nhất và bé nhất của kiểu dữ liệu một cách dễ dàng như sau:


let maxNumber = UInt8.max // kết quả là 255 với kiểu dữ liệu Unsigned Integer 8-bit let minNumber = UInt8.min // kết quả là 0 với kiểu dữ liệu Unsigned Integer 8-bit


Kiểu Int


 


  • Ở kiến trúc 32-bit, Int có cùng kích thước với Int32
  • Ở kiến trúc 64-bit, Int có cùng kích thước với Int64

 


Int có giá trị nằm trong khoảng -2,147,483,648 và 2,147,483,647


 


Kiểu UInt*


 


  • Ở kiến trúc 32-bit, Int có cùng kích thước với UInt32
  • Ở kiến trúc 64-bit, Int có cùng kích thước với UInt64

 


Số thập phân (Floating Number)


 


  • Double là kiểu dữ liệu số thập phân 64-bit
  • Float là kiểu dữ liệu số thập phân 32-bit

Type Safety và Type Inference


 


Swift là một ngôn ngữ hỗ trợ kiểu an toàn (Type Safe, bắt đầu từ đây mình ghi Type Safe luôn vì dịch ra sẽ không sát và không hay lắm). Vì thế một ngôn ngữ Type Safe luôn khuyến khích bạn chỉ ra rõ ràng là bạn đang làm việc với kiểu dữ liệu nào. Ví dụ như một đoạn code bạn đang xử lí kiểu chuỗi (string), thì bạn sẽ không thể coi nó như là 1 số nguyên (int) được.


 


Vì Swift là một ngôn ngữ Type Safe, vì thế complier sẽ tự động kiểm tra kiểu dữ liệu và bắt lỗi giúp bạn. Điều đó sẽ giúp bạn dễ dàng hơn trong việc fix những lỗi này ngay trong thời gian đang phát triển.


 


Vì complier sẽ kiểm tra kiểu dữ liệu ở các biến cũng như hằng khi bạn gán một kiểu dữ liệu khác với kiểu dữ liệu mà biến / hằng đang lưu trữ và sẽ báo lỗi. Nếu trong lúc khai báo biến / hằng, bạn không định nghĩa trước biến / hằng đó chứa kiểu dữ liệu gì, thì Swift sẽ sử dụng Type Inference để tự động định nghĩa giúp bạn từ dữ liệu ban đầu mà bạn gán cho nó.
Ví dụ


 


    let meaningOfLife = 42

// meaningOfLife sẽ mang kiểu Int

 


Tuy nhiên, có một lưu ý nho nhỏ là Swift ưu tiên sử dụng kiểu Double hơn là kiểu Float
Ví dụ


 


let pi = 3.14159

// pi sẽ mang kiểu dữ liệu là Double

 


Cách viết số (Numeric Literals)


 


  • Với số kiểu decimal, có thể viết dưới dạng không có tiền tố (prefix)
  • Với kiểu binary, tiền tố sẽ là 0b
  • Với kiểu octal, tiền tố sẽ là 0o
  • Với kiểu hexadecimal, tiền tố sẽ là 0x

 


Tất cả các số dưới đây đều có giá trị 17 ở kiểu decimal


 


let decimalInteger = 17

let binaryInteger = 0b10001
let octalInteger = 0o21
let hexadecimalInteger = 0x11

 


Ngoài ra, với số mũ ở dạng decimal. Bạn có thể viết như sau:
1.25e2 có nghĩa là 1.25 * 10^2 = 125.0
1.25e-2 có nghĩa là 1.25 * 10^-2 = 0.0125


 


Tương tự với hexadecimal
0xFp2 có nghĩa là 15 * 2^2 = 60
0xFp-2 có nghĩa là 15 * 2^-2 = 3.75


 


Chuyển đổi số nguyên
Các bạn xem ví dụ dưới đây:


 


 let cannotBeNegative: UInt8 = -1

// Kiểu Unit8 không thể chứa số âm, vì thế sẽ báo lỗi ở đây
let tooBig: Int8 = Int8.max + 1
// Tương tự ở đây với kiểu Int8 không thể chứa 1 số lớn hơn kiểu dữ liệu mà nó cho phép
// Và vì thế cũng sẽ báo lỗi

 


Vậy để chứa 1 số lớn hơn kiểu dữ liệu hiện tại khi cộng 2 số thì sao?
Có thể làm như sau:


 


let twoThousand: UInt16 = 2_000

let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16(one)

 


Đó là lợi dụng Type Inference của Swift, ta chuyển 2 số cần cộng lại về cùng 1 kiểu dữ liệu, như ở trên là UInt16. Sau đó tạo 1 hằng(biến) mới để cộng lại. Khi đó, Swift sẽ hiểu là kiểu dữ liệu của hằng(biến) mới sẽ mang kiểu dữ liệu nào để phù hợp với kết quả của phép cộng.


 


Chuyển đổi số nguyên và số thập phân
Các bạn xem ví dụ bên dưới
Ví dụ:


 


let three = 3

let pointOneFourOneFiveNine = 0.14159
let pi = Double(three) + pointOneFourOneFiveNine
// pi sẽ mang giá trị 3.14159, và kiểu dữ liệu sẽ là Double

 


Hoặc ta có thể lấy phần nguyên của 1 số thập phân tương tự như trong C như sau:


 


let IntPi = Int(3.14159)

// IntPi mang giá trị là 3 và kiểu Int

 


Bí danh kiểu dữ liệu (Type Aliases)


 


Type Aliases sẽ là một tên bí danh cho một kiểu dữ liệu hiện tại. Hiểu đơn giản là đặt một cái tên khác cho một kiểu dữ liệu đang có.


 


typealias DayLaKieuInt32 = UInt32


 


Đơn giản vậy thôi :smile: lâu lâu đặt tên một kiểu dữ liệu nào đó bá đạo để giải trí cũng được đấy chứ.


 


Kiểu Bool


 


Kiểu Bool này đã quá quen thuộc với tất cả mọi developer rồi nhỉ, kiểu bool sẽ mang giá trị là true hoặc false.
Tuy nhiên, Swift hơi khó tính 1 chút, không có dễ dãi giống như trong C. Bạn có thể xem ví dụ bên dưới để xem nó khó tính kiểu gì nhé.


 


let PQT_Handsome = true

if PQT_Handsome
{
print ("PQT Handsome")
}
//Mọi thứ hoạt động tốt, không có error, không warning

 


Tuy nhiên


 


let PQT_Handsome = 1

if PQT_Handsome
{
// Complier sẽ báo lỗi ngay lập tức, hơi khó tính nhỉ Unhappy
}
// Nhưng có thể làm như sau
if PQT_Handsome == 1
{
// Ồ, mọi thứ ok rồi
}

 


Tuples


 


Đây là một điểm khá hay ở Swift, Tuples sẽ giúp bạn trả về 2 hay nhiều thứ từ một hàm, điểm này mình nghĩ một số ngôn ngữ khác nên học tập :smile:
Ví dụ:


 


let TenTuoiNghe = ("Pham Quoc Thang", 18, "Sinh Vien")

// TenTuoiNghe sẽ mang kiểu dữ liệu (String, Int, String)

 


Để lấy dữ liệu bạn cần từ Tuples trên, bạn có thể làm như sau.


 


let TenTuoiNghe = ("Pham Quoc Thang", 18, "Sinh Vien")

let (Ten, Tuoi, Nghe) = TenTuoiNghe

 


Hoặc nếu muốn lấy 1 hay vài thứ từ Tuples trên, còn lại không quan tâm thì có thể làm như sau


 


let TenTuoiNghe = ("Pham Quoc Thang", 18, "Sinh Vien")

let (Ten, _, _) = TenTuoiNghe
// Ten sẽ mang giá trị Pham Quoc Thang và còn lại thì bỏ qua hết


Optionals


 


Sở dĩ mình để nguyên Optionals là vì mình cũng không biết phải dịch làm sao cho dễ hiểu mà không mất đi ý nghĩa của nó. Vì thế các bạn chịu khó xem ví dụ bên dưới để hình dung :smile:


let strNumber = "123" let number = Int(strNumber)


Đoạn code trên dùng để convert String sang Int. Tuy nhiên, nếu String kia không phải là 123, mà là "hello kipalog" thì sao? Ở một số ngôn ngữ khác, đặc biệt là C# 5 trở xuống sẽ báo lỗi. Còn C# 6 thì có kiểu Int?. Swift cũng tương tự như vậy!


let strNumber = "123aaa" let number = Int(strNumber)


Lúc này number sẽ mang kiểu Int? và vì strNumber không phải 1 số, nên number sẽ mang giá trị nil (null ấy)


 


nil
nil cũng là null trong các ngôn ngữ lập trình khác, và hiển nhiên. Mặc định bạn khai báo một biến nào đó mà không có giá trị, Swift sẽ tự gán cho biến đó giá trị nil


 


Optionals Binding


if let actualNumber = Int(possibleNumber) { print("\'\(possibleNumber)\' mang giá trị là \(actualNumber)") } else { print("\'\(possibleNumber)\' không thể ép kiểu sang số nguyên") }


Đoạn code trên có thể hiểu đơn giản thế này.
"Nếu actualNumber nhận giá trị nào đó khác nil thì in ra giá trị của nó và ngược lại. Khi không thể ép kiểu qua string thì actualNumber sẽ mang giá trị nil và khi đó in ra ..."


 


Implicitly Unwrapped Optionals
Bên trên mình có nói đến việc kiểu Int? thì sẽ trả về nil khi không thể ép kiểu được. Vậy nếu muốn gán một biến/hằng kiểu Int bằng một biến/hằng kiểu Int? hay String bằng String? thì sao?


let possibleString: String? = "An optional string." let forcedString: String = possibleString! // Yêu cầu có dấu chấm than ở cuối let assumedString: String! = "An implicitly unwrapped optional string." let implicitString: String = assumedString // Không yêu cầu dấu chấm than


Dấu chấm than (!) đóng vai trò như khẳng định. Nghĩa là bắt buộc phải gán 1 giá trị cho biến/hằng ngay khi nó được khởi tạo.
Dấu chấm hỏi (?) thì không yêu cầu phải gán giá trị khi khởi tạo.
Cả 2 đều giống nhau ở điểm là có thể chứa được giá trị nil


let assumedString: String = nil // lỗi, phải dùng String? hoặc String! let assumedString2: String = "" // chạy ok


Kiểm soát lỗi (Error Handling)


 


Tương tự như các ngôn ngữ khác, Swift cũng có throws / try-catch để bẫy lỗi, kiểm soát lỗi.
Ví dụ:


func canThrowAnError() throws { // function này có thể có hoặc không có lỗi }


Hoặc bạn cũng có thể bẫy lỗi rồi xuất ra màn hình hay lưu log ở đâu đó bằng cách dùng try-catch
Ví dụ:


do { try canThrowAnError() } catch { }


Bạn có thể tìm hiểu chi tiết hơn về Error Handling tại website của apple. Error Handling


 


Debugging with Assertions


 


Assertions trong Swfit đóng vai trò như là một trigger, nó sẽ tự động kiểm tra dữ liệu đầu vào và thông báo. Cách khai báo Assertion như sau:


 



assert(biểu thức toán tử trả về kiểu bool, thông báo xuất ra khi toán tử trả về false)



let age = -3 assert(age >= 0, "Tuổi của một người không thể nhỏ hơn 0")


Nguồn dịch từ: The Swift Programming Language