Skip to content
  • Home
  • Code
  • iOS & Swift
  • Combine
  • RxSwift
  • SwiftUI
  • Flutter & Dart
  • Tutorials
  • Art
  • Blog
Fx Studio
  • Home
  • Code
  • iOS & Swift
  • Combine
  • RxSwift
  • SwiftUI
  • Flutter & Dart
  • Tutorials
  • Art
  • Blog
dart
Written by chuotfx on July 12, 2022

Functions – Dart Tour

Flutter & Dart

Contents

  • Chuẩn bị
  • Functions là gì?
    • Cú pháp
    • Gọi hàm
  • Parameters
    • Sử dụng nhiều tham số
    • Parameters optional
    • Default values
    • Naming parameters
    • Named parameters required
  • Optional types
  • Anonymous functions
    • Ý nghĩa
    • Sử dụng cơ bản
    • Returning a function
    • Closures and scope
  • Arrow functions
    • Cú pháp
    • Ví dụ 1 cho các function ẩn danh
    • Ví dụ 2 cho các function trả về function
    • Ví dụ với các ForEach
  • Tạm kết

Chào mừng bạn đến với Fx Studio. Chúng ta tiếp tục chuyến du lịch với series Dart Tour không đồng đầy thú vị. Chủ đề cho bài viết này là Functions. Đây cũng làm 1 trong những khái niệm cơ bản của Dart & Flutter. Bạn sẽ hơi bỡ ngỡ một tí, vì với ngôn ngữ Dart có nhiều thứ huyền bí lắm.

Nếu mọi việc đã ổn rồi, thì …

Bắt đầu thôi!

Chuẩn bị

Về mặt công cụ editor thì khá đơn giản:

  • TextEditor
  • Visual Studio Code (nên dùng)

Hoặc bạn vào trang https://dartpad.dev/ để tiến hành code luôn. Khá là giống với Playground của Swift.

Vè mặt lý thuyết, nếu bạn chưa biết gì về Dart, thì có thể theo dõi lại các bài viết trong series Dart Tour nhóe.

Functions là gì?

Câu hỏi hơi ngáo một chút. Nhưng lâu nay, ít ai tự trả lời những cái mà ai cũng nghĩ là hiển nhiên hết. Về định nghĩa, functions (hàm) là một khối lệnh nhằm thực hiện một nhiệm vụ nhất định nào đó.

Cấu trúc cơ bản sẽ là:

Input => [ Function ] => Output

  • Input là các đối số được truyền vào cho các tham số của function
  • Output là giá trị trả về của function, nếu không có gì trả về kiểu void (không phải là không có trả gì về hết)

Mục đích duy nhất mà function được sinh ra là:

Tránh lặp lại những đoạn code giống nhau về cách xử lý thông tin.

Cú pháp

Ta sẽ phân tích cú pháp của một function tiêu chuẩn trong ngôn ngữ Dart thông qua ví dụ sau nhoé:

String hello(String name) {
  return 'Hello. I am $name';
}

Trong đó:

  • Return Type: đó là phần đầu tiên trong dòng khai báo function. Trong ví dụ là kiểu String
  • Function Name: là tên function, phần tiếp theo sau Return Type. Trong ví dụ tên function là hello
  • Parameters: là các tham số cho function, có thể có 1 hoặc nhiều tham số, hoặc không có tham số nào hết. Chúng được khai báo trong dấu (). Chia thành 2 phần:
    • Parameter Type: kiểu của tham số (phần từ trước)
    • Parameter Name: là tên của tham số (phần tử sau)
  • Return Value: giá trị mà function trả về, nó sẽ được gửi trong lệnh return ở bên trong function
  • Function body: toàn bộ các dòng lệnh trong 2 dấu { }

Gọi hàm

Sau khi định nghĩa xong function trong Dart, chúng ta sẽ thực hiện việc gọi hàm thực thi. Bạn xem tiếp ví dụ nha:

void main() {
  var str = hello("Fx Studio");
  print(str);
}

Trong đó:

  • Bạn sử dụng 2 dấu () để gọi thực thi một function. Bằng việc để nó ở sau tên hàm, ví dụ hello()
  • Fx Studio là đối số được truyền vào function. Nó tương ứng cho tham số name mà ta đã khai báo ở trên
  • Output được gán cho biến str. Đây là String được trả về trong lệnh return

Ngoài ra, functions trong Dart vẫn giống như các ngôn ngữ khác. Bạn hoàn toàn tự tin mà áp dụng theo các cách bạn đã biết.

Parameters

Chúng ta sẽ nói về các tham số cho các functions trong Dart tiếp nhoé. Chúng cũng khá linh hoạt đó.

Sử dụng nhiều tham số

Dart vẫn hỗ trợ khai báo nhiều tham số trong 1 function. Các tham số cách nhau bởi dấy ,. Xem ví dụ nha:

void helloPersonAndPet(String person, String pet) {
  print('Hello, $person, and your furry friend, $pet!');
}

Ta có function và 2 tham số. Bạn muốn thêm gì, thì cứ thêm vào nhoé. Còn gọi hàm thì đơn giản như sau:

helloPersonAndPet('Nick', 'Boo');

Các đối số truyền vào lần lượt và cũng cách nhau bởi dấu ,.

Tới đây, Swift & Objective-C của chúng ta đã khác xa với phần còn lại của thế giới. Khi chúng có thêm name & label cho các tham số của function.

Parameters optional

Dart hỗ trợ thêm cho function một chức năng khá là hay. Biến tham số khai báo trở lên là optional. Có nghĩa là:

Có thể có trong lời gọi hàm, hoặc không có vẫn không sao.

Các tham số này sẽ được khai báo trong 2 dấu [] và kiểu dữ liệu của chúng sẽ là Optional (tìm hiểu sau nhoé).

Ví dụ nhoé!

String fullName(String first, String last, [String? title]) {
  if (title != null) {
    return '$title $first $last';
  } else {
    return '$first $last';
  }
}

Trong đó:

  • title là tham số tuỳ chọn.

Và cách gọi hàm đó như sau:

print(fullName('Fx', 'Studio'));

print(fullName('Albert', 'Einstein', 'Professor'));

Bạn sẽ thấy ưu điểm của nó trong lời gọi hàm. Bạn sẽ không cần viết nhiều functions với việc chỉ bỏ đi 1 vài tham số.

Default values

Để cung cấp giá trị mặc định cho các tham số, thì giá trị sẽ được để sau dấu = cho từng tham số. Khi có giá trị mặc định, khi gọi hàm nếu không được cung cấp đối số, thì function sẽ lấy giá trị mặc định được khai báo.

Nếu không có giá trị mặc định, thì sẽ là null. Giống ở phần trên. Do đó, chúng ta cũng có thể khai báo chúng vào trong 2 dấu [].

Xem ví dụ nhoé:

String fullName2(String first, String last, [String title = 'Ahihi']) {
  return '$title $first $last';
}

Cung cấp giá trị mặc định cho title là ahihi. Cách gọi cũng tương tự.

print(fullName2('Fx', 'Studio'));

print(fullName2('Albert', 'Einstein', 'Professor'));

Với cách cung cấp Default Values thì sẽ loại trừ đi các trường hợp null của các Parameters optional. Nên bạn cần hết sức lưu ý khi code nhóe.

Naming parameters

Để không thua kém Swift, thì Dart cũng hỗ trợ thêm các name cho các tham số. Trong khai báo, chúng ta sẽ đặt các tham số này vào trong các dấu {}. Chúng có:

  • tên khi gọi hàm, làm cho ý nghĩa của các tham số được rõ ràng hơn
  • có thể optional để bỏ qua giá trị, tức là null
  • có giá trị mặc định, được gán sau dấu = của mỗi tham số

Ví dụ sau:

bool withinTolerance(int value, {int min = 0, int max = 10}) {
  return min <= value && value <= max;
}

Gọi thực thi như sau:

withinTolerance(9, min: 7, max: 11);

Bạn để ý giữa 9 và min: 7 và max: 11. Sự khác biệt ở các dữ min & max xuất hiện trong lời gọi hàm.

Hình bóng của Swift đã quay về rồi. Ahihi!

Named parameters required

Có một lỗi nhẹ, thực chất là sự bỏ qua suggestion cho lời gọi làm. Khi các tham số trong {} không được liệt kê ra. Và để muốn chắc chắn bạn phải cung cấp giá trị cho các tham số đó. Thì hãy sử dụng thêm từ khoá required vào trước các tham số nào cần thiết phải có trong lời gọi hàm.

Sửa lại ví dụ trên như sau:

bool withinTolerance2({required int value, required int min, required int max}) {
  return min <= value && value <= max;
}

Bạn sẽ thấy khác biệt khi gọi hàm này với việc suggestion từ các IDE nhoé.

Lưu ý, với từ khoá required thì sẽ không dùng được giá trị mặc định cho tham số.

Optional types

Được xem là một tính năng đặc biệt của functions trong Dart. Bạn có thể lượt bỏ đi phần Return Type trong khai báo function.

compliment(number) {
  return '$number is a very nice number.';
}

Với khai báo function như trên, Dart sẽ hiểu kiểu trả về của function là một kiểu dạng dynamic. Mặc dù, Dart có thể suy luận ra kiểu trả về là String bên trong hàm. Ngoài ra, với khai báo kiểu này, bạn có thể bỏ qua cả kiểu dữ liệu của tham số. Nếu bạn chú ý kĩ về khai báo number ở ví dụ trên.

Và ví dụ trên, tương đương với khai báo sau:

String compliment(dynamic number) {
  return '$number is a very nice number.';
}

Thực thi function và cảm nhận kết quả nhóe!

Anonymous functions

Dart cũng rất thú vị, khi bạn có thể bỏ luôn tên functions biến chúng trở thành hàm ẩn danh (anonymuos function). Chúng ta tiếp tục khám phá chúng nó qua các phần sau đây.

Nghe qua thì cao sang quyền quý như vậy, nhưng thực chất đó là phiên bản …

Closure của Swift cho Dart mà thôi.

Ý nghĩa

  • Biến 1 function thành một biến hay khai báo 1 biến với kiểu dữ liệu là 1 function
  • Khai báo các tham số của một function là một kiểu function
  • Return giá trị trả về là một function

Tất cả những thứ này giống như Closure làm được bên Swift yêu dấu của chúng ta nhoé.

Sử dụng cơ bản

Bạn sẽ viết function mà không có kiểu trả về và tên hàm. Thì bạn sẽ có được một hàm ẩn danh. Cú pháp cơ bản như sau:

([[Type] param1[, …]]) {
  codeBlock;
};

Trong đó:

  • Các tham số ở trong dấu ()
  • Code sẽ ở trong 2 dấu {}
  • Kiểu trả về tuỳ thuộc vào giá trị return của function này

Ví dụ nhoé:

final multiply = (int a, int b) {
  return a * b;
};

Lúc này, multiply được xem là một biến. Tuy nhiên, kiểu dữ liệu của nó là một function và giá trị trả về tuỳ thuộc vào giá trị tham số truyền vào. Xem cách gọi biến thực thi nhoé.

print(multiply(2, 3));

Returning a function

Chúng ta sẽ tới phần 1 function return về một function. Tất nhiên, kiểu dữ liệu ở đây sẽ là Function, đây cũng chính là từ khoá cho kiểu viết này.

Ví dụ:

Function applyMultiplier(num multiplier) {
  return (num value) {
    return value * multiplier;
  };
}

Trong đó, Function ở đầu tiên được xem là một kiểu dữ liệu cho function applyMultiplier. Và kết quả trả về của applyMultiplier lại là 1 hàm ẩn danh.

Bắt đầu hơi điên về Dart rồi nhoé!

Xem tiếp ví dụ, với 1 biến tạo ra bởi kiểu Function trên.

final triple = applyMultiplier(3);

Lúc này, triple vẫn là 1 biến với kiểu là applyMultiplier. Chúng ta không thực thi được triple ngay lúc này. Mà nó vẫn là chỉ là function mà thôi.

Muốn thực thi tiếp thì như sau:

print(triple(6));

print(triple(14.0));

Vì hàm ẩn danh trong phần return lại cần 1 tham số nữa. Do đó, khi gọi biến này thực thi, bạn lại cung cấp thêm cho chúng 1 đối số tiếp.

Mệt não rồi nhoé!

Closures and scope

Anonymous functions in Dart act as what are known as closures.

Đây cũng là thưa nhận về Dart cho functions ẩn danh của nó là một bao đóng (closure). Chính vì các bao đóng này, mà sinh ra cái gọi làm phạm vi của biến.

Các biến có các phạm vi nhất định trong chính khối lệnh của nó, tức là 2 dấu {} nhoé.

Lấy lại ví dụ trên:

Function applyMultiplier(num multiplier) {
  return (num value) {
    return value * multiplier;
  };
}

Trong đó:

  • multiplier có phạm vi ảnh hưởng toàn bộ function này
  • value chỉ ảnh hưởng trong phạm vi function ẩn danh được trả về mà thôi

Ta có 1 ví dụ khác:

var counter = 0;
final incrementCounter = () {
  counter += 1;
};

Khi biến được khai báo ở ngoài bao đóng, thì hàm ẩn danh vẫn có thể truy cập và thay đổi giá trị của biến từ bên trong. Và ta gọi thực thi nhiều lần, thì đối tượng tác động chính là biến khai báo ở ngoài đó.

incrementCounter();
incrementCounter();
incrementCounter();
incrementCounter();
incrementCounter();
print(counter); //5

Kết quả lúc này sẽ là 5. Và cách này, cũng có ý nghĩa khi bạn sử dụng kiểu function trả về function. Xem ví dụ sau nhoé.

Function countingFunction() {
  var counter = 0;
  final incrementCounter = () {
    counter += 1;
    return counter;
  };
  return incrementCounter;
}

Cách sử dụng như sau:

final counter1 = countingFunction();
final counter2 = countingFunction();

print(counter1()); // 1
print(counter2()); // 1
print(counter1()); // 2
print(counter1()); // 3
print(counter2()); // 2

Các giá trị của counter1 và counter2 sẽ khác nhau và chúng nó không liên quan gì tới nhau. Bạn sẽ hiểu đơn giản là các biến countingFunction sẽ còn tồn tại theo các biến counter1 và counter2 còn tồn tại. Chúng sẽ tiếp tục được các functions ẩn danh bên trong sử dụng.

Nổ não nữa rồi!

Arrow functions

Cú pháp

Trong khi Swift với function chỉ có 1 dòng thì sẽ loại bỏ đi từ khoá return. Thì Dart từ trước đó, đã chơi trội hơn nhiều rồi. Khi Dart đưa ra một cú pháp đặc biệt cho function chỉ có 1 dòng.

Đó là  =>

Ta lấy ví dụ như sau:

int add(int a, int b) {
   return a + b; 
}

Thì có thể dùng cú pháp => để viết lại function trên cho gọn. Xem ví dụ nhoé!

int add(int a, int b) => a + b;

Và chúng ta cũng có thể áp dụng cú pháp này cho các function ẩn danh. Khi chỉ còn các tham số trong dấu ()và biểu thức sau dấu =>.

(parameters) => expression;

Okay! I’m fine.

Ví dụ 1 cho các function ẩn danh

Bạn có function sau:

final multiply = (int a, int b) {
  return a * b;
};

Chuyển đổi lại như sau:

final multiply = (int a, int b) => a * b;

Sử dụng thì như ri:

print(multiply(2, 3)); // 6

Ví dụ 2 cho các function trả về function

Ta lại có một ví dụ tiếp theo như sau:

Function applyMultiplier(num multiplier) {
  return (num value) {
    return value * multiplier;
  };
}

Đây là function trả về function và sử dụng một function ẩn danh để làm giá trị trả về. Ta cũng có thể viết lại như sau:

Function applyMultiplier(num multiplier) {
  return (num value) => value * multiplier;
}

Thấy gọn gàng hơn nhiều khi so với cách viết các functions lồng nhau bên trong thân hàm.

Ví dụ với các ForEach

Ví dụ, bạn có 1 array số nguyên và nhân mỗi phần tử với 4.

numbers.forEach((number) {
  final tripled = number * 4;
  print(tripled);
});

Ta sẽ viết lại cho no xịn sò hơn nhiều, thì trông như ri nè!

numbers.forEach((number) => print(number * 4));

Như vậy là bạn đã xong cơ bản về functions trong Dart rồi đó. Mệt não quá!

Tạm kết

  • Tìm hiểu về functions trong Dart
  • Cấu tạo của một function
  • Các vấn đề liên quan tới các tham số của hàm
  • Các hàm ẩn danh trong Dart
  • Tìm hiểu về các Arrow functions & các ví dụ sử dụng chúng

 

Okay! Tới đây, mình xin kết thúc bài viết về Functions trong series Dart Tour. Nếu có gì thắc mắc hay góp ý cho mình thì bạn có thể để lại bình luận hoặc gởi email theo trang Contact.

  • Bạn có thể checkout code tại đây.
  • Bài viết tiếp theo tại đây.

Cảm ơn bạn đã đọc bài viết này!

FacebookTweetPinYummlyLinkedInPrintEmailShares18

Related Posts:

  • Map type - Dart Tour
    Map type - Dart Tour
  • Chào thế giới! - Dart Tour
    Chào thế giới! - Dart Tour
  • Expressions - Dart Tour
    Expressions - Dart Tour
  • Control Flow - Dart Tour
    Control Flow - Dart Tour
Tags: dart, dart basic, dart tour, flutter
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

Your email address will not be published. Required fields are marked *

Donate – Buy me a coffee!

Fan page

Fx Studio

Tags

Actor Advanced Swift api AppDistribution Asynchronous autolayout basic ios tutorial blog callback ci/cd closure collectionview combine concurrency CoreData Core Location crashlytics darkmode dart dart basic dart tour Declarative decoding delegate deploy fabric fastlane firebase flavor flutter GCD iOS mapview MVVM optional protocol rxswift Swift Swift 5.5 SwiftUI SwiftUI Notes tableview testing TravisCI unittest

Recent Posts

  • Raw String trong 10 phút
  • Dispatch Semaphore trong 10 phút
  • Tổng kết năm 2022
  • KeyPath trong 10 phút – Swift
  • Make color App Flutter
  • Ứng dụng Flutter đầu tiên
  • Cài đặt Flutter SDK & Hello world
  • Coding Conventions – người hùng hay kẻ tội đồ?
  • Giới thiệu về Flutter
  • Tìm hiểu về ngôn ngữ lập trình Dart

You may also like:

  • Chào thế giới! - Dart Tour
    Chào thế giới! - Dart Tour
  • Multiplatform App : Extra Functions - SwiftUI Notes #24
    Multiplatform App : Extra Functions - SwiftUI Notes #24
  • Variables & Constant - Dart Tour
    Variables & Constant - Dart Tour
  • Object Oriented Programming (OOP) - Dart Tour
    Object Oriented Programming (OOP) - Dart Tour
  • Expressions - Dart Tour
    Expressions - Dart Tour

Archives

  • 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)

About me

Education, Mini Game, Digital Art & Life of coders
Contacts:
contacts@fxstudio.dev

Fx Studio

  • Home
  • About me
  • Contact us
  • Mail
  • Privacy Policy
  • Donate
  • Sitemap

Categories

  • Art (1)
  • Blog (22)
  • Code (4)
  • Combine (22)
  • Flutter & Dart (24)
  • iOS & Swift (86)
  • RxSwift (37)
  • SwiftUI (76)
  • Tutorials (70)

Newsletter

Stay up to date with our latest news and posts.
Loading

    Copyright © 2023 Fx Studio - All rights reserved.

    Share this ArticleLike this article? Email it to a friend!

    Email sent!