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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func printHelloWorld() { | |
print(“Hello World!”) | |
} |
Bắt đầu một hàm là từ khóa func và theo sau là tên của hàm(printHelloWorld) tiế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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
printHelloWorld() | |
// Hello World |
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.
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.
Ví dụ:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func printMessage(message: String) { | |
print(message) | |
} |
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ụ:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
printMessage(message: “Hello World!”) | |
// Hello World! |
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ụ:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
printMessage(message: “Hello World!”) |
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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func printMessage(message: String, times: Int) { | |
for i in 0..<times { | |
print(“\(i) \(message)”) | |
} | |
} | |
func printMessage(message: String) { | |
print(message) | |
} |
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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
func printDate(date: Date, format: String) { | |
let dateFormatter = DateFormatter() | |
dateFormatter.dateFormat = format | |
print(dateFormatter.string(from: date)) | |
} |
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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
printDate(date: Date()) // error: Thiếu đối số format truyền vào |
Vậy chúng ta có thể khắc phục điều đó như thế này:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func printDate(date: Date, format: String = “YY/MM/dd”) { | |
let dateFormatter = DateFormatter() | |
dateFormatter.dateFormat = format | |
print(dateFormatter.string(from: date)) | |
} |
Đị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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
printDate(date: Date()) |
Ngoài ra còn có thể gọi như thế này:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
printDate(date: Date(), format: “dd/MM/YY”) |
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ụ:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func printDate(date: Date, format: String = “YY/MM/dd”) -> String { | |
let dateFormatter = DateFormatter() | |
dateFormatter.dateFormat = format | |
return dateFormatter.string(from: date) | |
} |
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let formattedDate = printDate(date: Date(), format: “dd/MM/YY”) | |
print(formattedDate) |
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ụ:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} |
Swift cho phép chúng ta có thể viết gọn hơn như sau:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} |
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ụ:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} |
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ố:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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! |
Ví dụ về hàm là một giá trị trả về:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
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.
HXV.
0 Comments