Kiến thức cơ bản về Swift (Phần 3) – Hàm và Tham số kiểu hàm


Tiếp theo bài Hằng và Biến, Chúng ta sẽ tìm hiểu khái niệm về hàm(Function) trước khi tìm hiểu tới khái niệm về Class và Struct. Hàm chính là một trong những điểm mạnh và linh hoạt trong Swift nó cũng tựa tựa với Closure. Tương tự như các ngôn ngữ lập trình khác như C/C++/Objective-C, hàm trong Swift có cú pháp khá đơn giản và cách gọi để dùng cũng dễ dàng. Trong bài này chúng ta sẽ tập trung tìm hiểu một trong những kiến thức cơ bản về hàm. Bây giờ chúng ta sẽ tạo một playground mới và bắt đầu với những ví dụ về hàm như bên dưới.

1. Ví dụ về hàm

Hàm là một khối block và trong khối block đó sẽ thực hiện một xử lý logic nào đó hay một công việc nào đó. Một hàm(Function) sẽ không có quá 1 khối block { } và chúng ta có thể dùng hàm bất cứ khi nào cần. Chúng ta bắt đầu khám phá một ví dụ về hàm trong Swift:
func printHelloWorld() {
print(“Hello World!”)
}
view raw gistfile1.txt hosted with ❤ by GitHub

Bắt đầu một hàm là từ khóa func và theo sau là tên của hàm(printHelloWorldtiếp đó là phần thân của hàm, nó được bao bọc với 2 dấu {}, Vậy để sử dụng hàm chúng ta gọi như sau:
printHelloWorld()
// Hello World
view raw gistfile1.txt hosted with ❤ by GitHub

2. Tham số

Hãy làm cho ví dụ trên thêm phức tạp hơn tý bằng cách thêm cáctham số  để xác định thêm các chức năng của hàm. Trong hàm này chúng ta sẽ nhập thêm một giá trị và sử dụng nó trong phần thân hàm. Chúng ta sẽ định nghĩa tên hàm printMessage(message:) và một tham số message kiểu String.
Ví dụ:
func printMessage(message: String) {
print(message)
}
view raw gistfile1.txt hosted with ❤ by GitHub

Thay vì in cứng một chuỗi String bằng hàm printHelloWorld() thì bây giờ chúng ta sẽ in ra một chuỗi thông qua tham số message , cách này rất là linh hoạt và hữu dụng cho nhiều trường hợp khác nhau.
Ví dụ:
printMessage(message: “Hello World!”)
// Hello World!
view raw gistfile1.txt hosted with ❤ by GitHub

Lưu ý:
Có 2 khái niệm thường được dùng với hàm và thường gây ra nhầm lần cho các lập trình viên mới, đó là tham số(parameter) và đối số(arguments).Đối với Swift có sự khác biệt,
  • Tham số(parameters) là giá trị nào đó được mô tả khi khai báo hàm.
  • Đối số(arguments) của một hàm là giá trị được truyền vào hàm khi hàm đó được gọi.
Ví dụ:
printMessage(message: “Hello World!”)
view raw gistfile1.txt hosted with ❤ by GitHub
Ta sẽ hiểu như sau, hàm printMessage có tham số là message với kiểu String và có đối số là “Hello World”. Đơn giản đúng không các bạn.
Trong Swift, một hàm có thể có nhiều tham số và có thể định nghĩa nhiều hàm giống tên nhưng số lượng tham số phải khác nhau, như ví dụ sau:
func printMessage(message: String, times: Int) {
for i in 0..<times {
print(“\(i) \(message)”)
}
}
func printMessage(message: String) {
print(message)
}
view raw gistfile1.txt hosted with ❤ by GitHub

Hơn thế nửa hàm còn cho phép khi mô tả các tham số thì chúng ta được gán giá trị mặc định cho chúng. Chúng ta đến với ví dụ sau:
Để bắt đầu ví dụ bạn nên import thư viên: UIKit và định nghĩa hàm như sau:
import UIKit
func printDate(date: Date, format: String) {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format
print(dateFormatter.string(from: date))
}
view raw gistfile1.txt hosted with ❤ by GitHub

Với hàm trên có tham số kiểu ngày date và format cho kiểu ngày đó. Bây giờ chúng ta thử gọi hàm đó mà không cần đối số format, thì Xcode sẽ báo lỗi như sau:
printDate(date: Date()) // error: Thiếu đối số format truyền vào
view raw gistfile1.txt hosted with ❤ by GitHub

Vậy chúng ta có thể khắc phục điều đó như thế này:

func printDate(date: Date, format: String = “YY/MM/dd”) {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format
print(dateFormatter.string(from: date))
}
view raw gistfile1.txt hosted with ❤ by GitHub

Định nghĩa một giá trị mặt định cho tham số format, sau đó gọi lại hàm và hết nhận thông báo lỗi:
printDate(date: Date())
view raw gistfile1.txt hosted with ❤ by GitHub

Ngoài ra còn có thể gọi như thế này:
printDate(date: Date(), format: “dd/MM/YY”)
view raw gistfile1.txt hosted with ❤ by GitHub

Lưu ý:
Apple khuyến khích chúng ta nên đặt các tham số có giá trị mặc định ở phần cuối hàm, chắc chắn đó là một ý tưởng tốt và chung cho các lập trình viên trong trình bày code thêm chuyên nghiệp và đẹp hơn.

3. Kiểu trả về

Một hàm thì có thể có giá trị trả về hoặc không giá trị trả về, Vậy để mô tả một hàm có trị trả về ta dùng cú pháp -> sau danh sách các tham số của hàm.
Ví dụ:
func printDate(date: Date, format: String = “YY/MM/dd”) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format
return dateFormatter.string(from: date)
}
view raw gistfile1.txt hosted with ❤ by GitHub

Ta thấy cú pháp -> và kiểu trả về là String, và trong hàm có từ khóa return để trả về kết quả, bây giờ thử gọi hàm đó và xem kết quả như thế nào.

let formattedDate = printDate(date: Date(), format: “dd/MM/YY”)
print(formattedDate)
view raw gistfile1.txt hosted with ❤ by GitHub

Còn đối với hàm không có trị trả về thì chúng ta sẽ không cần dùng cú pháp -> và cũng không cần kiểu dữ liệu trả về khi định nghĩa một hàm, như ví dụ printHelloWorld() ở trên.
Một kiểu trả về khá tuyệt vời của hàm trong Swift đó là trả về kiểu Tuples hay gọi là kiểu dữ liệu trả về nhiều giá trị. Bạn có thể xem ví dụ bên dưới để hiểu rõ hơn.
Ví dụ:
func timeComponentsForDate(_ date: Date) -> (hour: Int, minute: Int, second: Int) {
let dateComponents = Calendar.current.dateComponents([.hour, .minute, .second], from: date) let hour = dateComponents.hour
let minute = dateComponents.minute
let second = dateComponents.second
return (hour ?? 0, minute ?? 0, second ?? 0)
}
view raw gistfile1.txt hosted with ❤ by GitHub

Swift cho phép chúng ta có thể viết gọn hơn như sau:
func timeComponentsForDate(_ date: Date) -> (Int, Int, Int) {
let dateComponents = Calendar.current.dateComponents([.hour, .minute, .second], from: date)
let hour = dateComponents.hour
let minute = dateComponents.minute
let second = dateComponents.second
return (hour ?? 0, minute ?? 0, second ?? 0)
}
view raw gistfile1.txt hosted with ❤ by GitHub

Khuyến khích chúng ta nên có thêm các tên tham số để về sau dễ dàng đọc và hiểu code hơn.
Và cuối cùng, hàm cũng có thể trả về giá tri kiểu Optional như sau:
Ví dụ:
func timeComponentsForDate(_ date: Date) -> (hour: Int, minute: Int, second: Int)? {
let dateComponents = Calendar.current.dateComponents([.hour, .minute, .second], from: date)
guard let hour = dateComponents.hour else {
return nil
}
guard let minute = dateComponents.minute else {
return nil
}
guard let second = dateComponents.second else {
return nil
}
return (hour, minute, second)
}
view raw gistfile1.txt hosted with ❤ by GitHub

4. Hàm là một tham số

Trong Swift, hàm cũng có thể hiểu như một kiểu dữ liệu vậy, nên nó có thể làm tham số hay kiểu trả về của một hàm nào đó. Ví dụ như (String) -> ()
Lưu ý:
Cú pháp () được hiểu là kiểu Void, đó là cách viêt tắt.
Ví dụ về hàm là một tham số:
func printMessage(_ message: String) {
print(message)
}
func printMessage(_ message: String, with function: (String) -> ()) {
function(message)
}
let myMessage = “Hello, world!”printMessage(myMessage, with: printMessage)
//Hello, world!
view raw gistfile1.txt hosted with ❤ by GitHub

Ví dụ về  hàm là một giá trị trả về:
func compute(_ addition: Bool) -> (Int, Int) -> Int {
func add(_ a: Int, _ b: Int) -> Int {
return a + b
}
func subtract(_ a: Int, _ b: Int) -> Int {
return a – b
}
if addition {
return add
} else {
return subtract
}
}
let computeFunction = compute(true)
let result = computeFunction(1, 2)
print(result)
view raw gistfile1.txt hosted with ❤ by GitHub

Với kiểu trả về là  (Int, Int) -> Int  đó cũng chính là một hàm, tuy mới lần đầu nhìn thì hơi rắc rối nhưng dần về sau sẽ quen và dễ hiểu thôi.
Trong bài viết này chúng ta đã tìm hiểu thêm một kiến thức cơ bản mới trong Swift. Quan trọng là các bạn phải hiểu được cú pháp của nó và thực hành nhiều để về sau khi tìm hiểu và học các bài viết tiếp theo sẽ dề dàng hơn. Chúng ta sẽ áp dụng bài này vào bài viết Class và Struct vì hàm thì được dùng nhiều trong Class và Struct.
Hy vọng các bạn thích và học được nhiều kiến thức từ bài viết này. Mong các bạn chia sẽ nó để mọi người cùng học và cùng trao đổi. Mọi thắc mắc hay trao đổi về bài viết, các bạn có thể để lại bình luận bên dưới mình sẽ hỗ trợ sớm nhất.
Chân thành cảm ơn các bạn đã theo dõi.
HXV.

Post a Comment

0 Comments