Contents
Nghe qua câu hỏi từ tiêu đề bài viết thì …
Hơi vô lý nhưng lại khá là thuyết phục.
Vô lý vì nó tưởng chừng như cái hiển nhiên, ai cũng biết là ai rồi. Thuyết phục vì cái gì cũng cần phải định nghĩa được. Có bao giờ bạn tự hỏi.
-
- Hàm (function) là gì?
- Có bao nhiêu loại function?
- …
Vâng, chào bạn tới với Fx Studio. Bài viết này sẽ giúp bạn giải thích 1 phần các câu hỏi vô lý trên. Nếu vô tình bạn đi phỏng vấn một công ty nào đó, mà người phỏng vấn hỏi bạn. Thì bạn vẫn có thể tự tin đáp trả.
Mình sẽ sử dụng ngôn ngữ lập trình
Swift
để mô tả cho phần code của bài viết này. Nào, bắt đầu thôi!
Chuẩn bị
- Không cần chuẩn bị gì hết
1. Funtion là gì?
Function hay gọi là hàm, là một đoạn mã nằm trong 2 dấu
{ }
. Nhằm thực hiện một tác vụ cụ thể nào đó.
Trong đó:
- Biểu tượng cho function chính là 2 dấu
{ }
. - Function được xác định thông qua
function name
- Có giá trị trả về
- Không có hoặc có một hoặc nhiều tham số
Quan trọng
Để thực thi một function thì phải cần tới toán tử
( )
. Các giá trị đối số sẽ được gởi vào trong 2 dấu () đó.
Cú pháp
<từ khoá functuon> <function name> ( [danh sách tham số] ) -> <kiểu giá trị trả về> {
//code
return <giá trị>
}
Đó là cú pháp đơn giản nhất để khai báo 1 function. Tuỳ thuộc vào từng ngôn ngữ lập trình mà sẽ có cách khai báo và từ khoá khác nhau. Ví dụ với Swift là func
.
2. Các dạng function phổ biến
Tham khảo sơ đồ trên thì chúng ta có thể phân loại các dạng function cơ bản, mà bất cứ ngôn ngữ lập trình nào cũng có. Có thể bạn đã làm qua hết, nhưng đôi lúc ngồi hệ thống lại thì cũng khá thú vị.
2.1. Public & Private function
Đây chính là phạm vi truy cập tới cho function. Nếu bạn muốn các class khác không dùng được thì sử dụng private
. Còn với public
thì bên ngoài sẽ gọi được nó.
2.2. Tham số
Function còn được chia ra 2 dạng cơ bản nữa:
- Có tham số
- Không có tham số
Với có tham số thì sẽ được chia ra 2 loại cơ bản tiếp theo:
- Có một tham số
- Có nhiều tham số
2.3. Giá trị trả về
Cũng đươc chia ra thành 2 loại cơ bản:
- Giá trị trả về là
void
, tức là không có giá trị trả về - Giá trị trả về khác void
Từ khoá được sử dụng chính là return
. Khi chạy tới return
thì function sẽ kết thúc.
2.4. Gọi hàm
Sự kết hợp giữa 2 yếu tố trên là tham số và giá trị trả về. Và cũng chia ra 2 dạng cơ bản:
- Gọi hàm đơn thuần
- Gọi hàm lồng nhau
Giá trị trả về của function này chính là giá trị cho tham số của function khác. Function có thể gọi trực tiếp từ việc truyền giá trị cho tham số của function khác.
3. Tham số và đối số?
Chắc bạn cũng nhiều lần hay hằng nghe tới 2 từ khoá tham số
và đối số
, hay parameter
và argument
. Hoặc nhiều lúc phát biểu thì một cách vô thức. Và có lúc nào bạn sẽ thắc mắc …
Tham số là gì?
Đối số là gì?
Phân biết giữa tham số và đối số?
Giải thích:
- Tham số (parameter) là một
biến
được khai báo trong prototype hoặc khai báo hàm. - Đối số (argument) là
giá trị
mà được truyền vào hàm (khi gọi hàm) tại vị trí của tham số.
Ta lấy ví dụ cho nhanh hiểu được
func add(a: Int, b: Int) -> Int { return a + b }
Trong đó:
a
vàb
chính là các tham số của functionadd
- Chúng là biến và được sử dụng trong function
- Nó có ý nghĩa ở trong function
Tiếp theo
let number1 = 10 let number2 = 87 print(add(a: number1, b: number2))
Trong đó:
number1
vànumber2
là 2 biến được khai báo với giá trị cho sẵn- chúng được truyền vào function
add
- Khi đó đối số sẽ là giá trị của 2 biến
number1
vànumber2
, chứ không phải là 2 biếnnumber1
vànumber2
- Nếu như
a
vàb
có thay đổi giá trị, thì giá trị của 2 biếnnumber1
vànumber2
vẫn giữa nguyên.
Dễ hiểu hơn nữa, thì chúng ta có thể truyền trực tiếp giá trị vào tham số của function.
add(a: 25, b: 76)
4. Function và Method
Đây cũng là một trong những khái niệm khá là đau não
. Vì theo cách diễn giải của người Việt mình thì …
Function là hàm, Method cũng là hàm. Liệu Function và Method liệu có gì khác nhau không?
Khi thế giới lập trình còn sơ khai, kỉ nguyên của hướng đối tượng chưa ra đời. Thì chỉ có các function. Nó được sinh ra với mục đích nhóm các đoạn code lại với nhau, để thực thi một tác vụ nào đó. Mục đích xâu xa của nó là tận dụng lại mã nguồn của chương trình.
Và rồi khi Hướng đối tượng được khai sinh. Mọi thứ thay đổi từ đây, function nó không phải là thứ duy nhất được tái sử dụng. Và yêu cầu đối với nó càng ngày càng cao hơn. Nên Method được ra đời. Method là function có liên quan đến một kiểu dữ liệu nhất định nào đó (class, struct, enum).
Phân loại cho Method:
- Instance method: bao đóng những công việc và chức năng dùng để làm việc với một instance của một kiểu dữ liệu nhất định.
- Type method: bao đóng những công việc và chức năng dùng để làm việc trực tiếp tới kiểu dữ liệu của chính nó.
Để cho dễ hiểu hơn nữa, thì function viết trong 1 class sẽ có 2 kiểu
- Stactic function : dùng chính tên class để gọi
- Non-static function: dùng đối tượng của class để gọi
Tham khảo code bên Swift xem nó như thế nào 😎
class SomeClass { func someInstanceMethod() { //function body } class func someTypeMethod() { //function body } } let instance = SomeClass() instance.someInstanceMethod() SomeClass.someTypeMethod()
Tạm thời chúng ta đi qua sơ lượt hết các khái niệm và phân loại function trong lập trình. Có thế thiếu nhiều điều nhưng hi vọng đó cũng đủ cho bạn có 1 cái nhìn hình dung cụ thể function là gì.
Bây giờ, chúng ta sang ngôn ngữ lập trình Swift, xem function trong nó có cái gì hay. Tiếp tục thôi!
5. Đặc trưng của Swift
5.1. Cú pháp function
Tham khảo đoạn code sau:
func hello(name: String) -> String { return "Hello, " + name } print(hello(name: "Nick"))
Trong đó:
func
từ khoá khai báo 1 function- Tên của function là
hello
name
là tham số kiểu String- Giá trị trả về của function là String
hello(name: "Nick")
gọi function thực thi
5.2. Trả về nhiều giá trị
Bài toán, tìm min
và max
của một mãng số nguyên
func minMax(array: [Int]) -> (min: Int, max: Int) { 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) }
Sử dụng
let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) print("min is \(bounds.min) and max is \(bounds.max)")
Với Swift, thì chúng ta có thể trả về nhiều giá trị một lúc trong 1 lời gọi hàm. Thực chất chúng là kiểu Tuple
, nó nhóm các kiểu giá trị lại vào nhau. Mang tính chất nhất thời, không có tính kế thừa, không cần phải khai báo.
5.3. Argument Labels và Parameter Names
Cách truyền thống với tham số
func someFunction(firstParameterName: Int, secondParameterName: Int) { // In the function body, firstParameterName and secondParameterName // refer to the argument values for the first and second parameters. } someFunction(firstParameterName: 1, secondParameterName: 2)
Nhưng Swift thừa hưởng lại từ Objective-C. Và chúng ta có thêm 1 cách nữa với Argument Labels
.
func someFunction(argumentLabel parameterName: Int) { // In the function body, parameterName refers to the argument value // for that parameter. }
Nó giúp cho việc gọi hàm được tường minh. Đây là đặc trưng riêng của Swift. Ví dụ:
func greet(person: String, from hometown: String) -> String { return "Hello \(person)! Glad you could visit from \(hometown)." } print(greet(person: "Bill", from: "Cupertino"))
Nhưng nhiều bạn vẫn mang trong mình định kiến của các ngôn ngữ khác khi học iOS hay Swift. Và Apple cũng khá chịu chơi khi cho Swift có thể linh hoạt. Để bỏ đi hết các Argument Label
hay Parameter Names
thì bạn hãy dùng tới dấu _
trước các tham số.
func add(_ a: Int, _ b: Int) -> Int { return a + b } let number1 = 10 let number2 = 87 print(add(number1,number2)) add(25, 76)
Các gọi function thì rất giống C/C++ hay Java nhĩ!
Tóm tắt chút:
- Function trong swift sẽ có 2 tên
- Argument Label : dùng để hiển thi bên ngoài khi gọi function và truyền đối số vào. Giúp cho lời gọi hàm tường minh hơn.
- Parameter Name: dùng bên trong function, là tên của biến
- Nếu thiếu Argument Label thì Parameter Name sẽ đảm bảo luôn nhiệm vụ của của cả 2
- Muốn bỏ luôn 2 cái tên trong lời gọi hàm thì hãy dùng
_
5.4. In-Out Parameters
var a = 10 print("Before a = \(a)") func change(a: Int) { a = a + 1 } change(a: a) print("After a = \(a)")
Với đoạn code trên, thì chúng ta không thay đổi giá trị của a, các tham số trong function sẽ được hiểu là hằng số (let
). Vậy muốn cho nó có thể thay đổi giá trị của chính tham số thì sử dụng từ khoá inout
. Tiếp
var a = 10 print("Before a = \(a)") func change(a: inout Int) { a = a + 1 } change(a: &a) print("After a = \(a)")
Chú ý:
&
dùng để truy cập tới vùng nhớ của biến a được khai báo bên ngoài.
5.5. Function Type
Khai báo 1 function cho vui nào,
func addTwoInts(_ a: Int, _ b: Int) -> Int { return a + b }
Tiếp tục khai báo thêm 1 biến,
var mathFunction: (Int, Int) -> Int = addTwoInts
Trong đó:
(Int, Int) -> Int
là kiểu của biếnmathFunction
- function
addTwoInts
được gán cho biến trên
print("Result: \(mathFunction(2, 3))")
Sử dụng biến mathFunction
để thực thi với 2 đối số cho nó.
Với ví dụ trên thì ta thấy, để phân biệt các function khác nhau thì sẽ thông qua
- Danh sách tham số
- Giá trị trả về
Các yếu tố như tên tham số, tên function đều không có ý nghĩa. Để hiểu hơn thì bạn có thể tham khảo bài viết sau:
5.6. Function trong function
Chúng ta tham khảo tiếp 1 đoạn code sau
func hamKyDieu(soA: Int) -> Int { func tang1(so: Int) -> Int { return so + 1 } func giam1(so: Int) -> Int { return so - 1 } return tang1(so: soA) + giam1(so: soA) } hamKyDieu(soA: 10)
Điều kì diệu là trong function thì chúng ta vẫn có thể khai báo thêm function được nữa. Đó gọi là nested function
. Mục đích:
- Tách các đoạn code xử lý ra khi function quá lớn
- Chia nhỏ hơn cho các tác vụ trong 1 function
5.7. Không còn return
Đây là điểm mới nhất với Swift 5.1
func hello(name: String) -> String { "Hello, " + name }
Với function chỉ có 1 line
duy nhất thì bạn có thể bỏ đi từ khoá return
.
Tới đây thì mình xin kết thúc bài. Về function, thì bài viết này cung cấp thêm một số khái niệm nâng cao hơn so với các bài cơ bản trước đây.
Tạm kết
- Biết về function là gì
- Phân loại được chúng
- Các kiểu function
- Tham số và đối số
- Function và Method
- Các đặc trưng của function trong Swift
Cảm ơn bạn đã theo dõi bài viết này!
Written by chuotfx
Hãy ngồi xuống, uống miếng bánh và ăn miếng trà. Chúng ta cùng nhau đàm đạo về đời, về code nhóe!
Leave a Reply Cancel reply
Fan page
Tags
Recent Posts
- Charles Proxy – Phần 1 : Giới thiệu, cài đặt và cấu hình
- Complete Concurrency với Swift 6
- 300 Bài code thiếu nhi bằng Python – Ebook
- Builder Pattern trong 10 phút
- Observer Pattern trong 10 phút
- Memento Pattern trong 10 phút
- Strategy Pattern trong 10 phút
- Automatic Reference Counting (ARC) trong 10 phút
- Autoresizing Masks trong 10 phút
- Regular Expression (Regex) trong Swift
Archives
- September 2024 (1)
- July 2024 (1)
- June 2024 (1)
- May 2024 (4)
- April 2024 (2)
- March 2024 (5)
- January 2024 (4)
- February 2023 (1)
- January 2023 (2)
- November 2022 (2)
- October 2022 (1)
- September 2022 (5)
- August 2022 (6)
- July 2022 (7)
- June 2022 (8)
- May 2022 (5)
- April 2022 (1)
- March 2022 (3)
- February 2022 (5)
- January 2022 (4)
- December 2021 (6)
- November 2021 (8)
- October 2021 (8)
- September 2021 (8)
- August 2021 (8)
- July 2021 (9)
- June 2021 (8)
- May 2021 (7)
- April 2021 (11)
- March 2021 (12)
- February 2021 (3)
- January 2021 (3)
- December 2020 (3)
- November 2020 (9)
- October 2020 (7)
- September 2020 (17)
- August 2020 (1)
- July 2020 (3)
- June 2020 (1)
- May 2020 (2)
- April 2020 (3)
- March 2020 (20)
- February 2020 (5)
- January 2020 (2)
- December 2019 (12)
- November 2019 (12)
- October 2019 (19)
- September 2019 (17)
- August 2019 (10)