- Dart OOP là gì?
Dart OOP là lập trình hướng đối tượng (Object-Oriented Programming) trong ngôn ngữ Dart. Đây là phương pháp lập trình tổ chức chương trình xoay quanh đối tượng (Object) thay vì chỉ sử dụng các biến và hàm riêng lẻ.
Trong OOP, một đối tượng thường có dữ liệu và hành vi. Dữ liệu mô tả đặc điểm của đối tượng, còn hành vi mô tả những việc đối tượng có thể thực hiện.
Ví dụ, trong một ứng dụng bán hàng, một sản phẩm có thể có tên, giá, số lượng và các hành động như tính giá hoặc hiển thị thông tin. Những dữ liệu và hành động này có thể được gom lại thành một đối tượng Product.
Để tạo ra các đối tượng, Dart sử dụng Class. Class có thể hiểu là một khuôn mẫu mô tả đối tượng sẽ có những dữ liệu và hành vi gì.
Có thể hiểu mối quan hệ cơ bản như sau:
Class → Object → Dữ liệu + Hành vi
Dart OOP giúp chương trình có cấu trúc rõ ràng hơn, dễ quản lý, dễ tái sử dụng và dễ mở rộng. Đây là kiến thức nền tảng rất quan trọng đối với Flutter vì Flutter được xây dựng bằng Dart và sử dụng Class, Object cùng các đặc điểm của OOP ở hầu hết các thành phần.
- Class là gì?
Class là khuôn mẫu dùng để mô tả cấu trúc và hành vi của một nhóm đối tượng.
Class không phải là một đối tượng cụ thể mà chỉ là bản thiết kế cho đối tượng. Trong Class thường có:
- Property/Field: dùng để lưu trữ dữ liệu.
- Method: dùng để mô tả hành vi hoặc chức năng.
- Constructor: dùng để khởi tạo Object.
Ví dụ đơn giản:
class Student {
String name;
int age;
Student(this.name, this.age);
}
Trong ví dụ trên, Student là Class, còn name và age là dữ liệu mà mỗi Object Student có thể sở hữu.
Class giúp lập trình viên mô tả một đối tượng một cách có tổ chức thay vì phải quản lý từng biến riêng lẻ.
- Object là gì?
Object là một đối tượng cụ thể được tạo ra từ Class.
Nếu Class là khuôn mẫu thì Object là sản phẩm được tạo ra dựa trên khuôn mẫu đó.
Một Class có thể tạo ra nhiều Object. Các Object được tạo từ cùng một Class có cùng cấu trúc nhưng dữ liệu của từng Object có thể khác nhau.
Ví dụ:
Student student1 = Student("Thương", 20);
Student student2 = Student("Tiến", 21);
Ở đây student1 và student2 là hai Object khác nhau nhưng đều được tạo từ Class Student.
Trong ứng dụng thực tế, điều này rất hữu ích vì một Class có thể được sử dụng để tạo ra rất nhiều đối tượng có cùng loại dữ liệu.
- Property và Method
Trong một Class, dữ liệu và hành vi thường được thể hiện thông qua Property/Field và Method.
Property/Field là những biến được khai báo bên trong Class để lưu trữ thông tin của Object.
Ví dụ một sản phẩm có thể có:
- Tên sản phẩm
- Giá
- Số lượng
- Mã sản phẩm
Đây là những dữ liệu thuộc về sản phẩm.
Method là các hàm được khai báo bên trong Class để thực hiện một hành động.
Ví dụ một sản phẩm có thể có các hành động:
- Hiển thị thông tin
- Tính giá
- Cập nhật số lượng
Việc đặt dữ liệu và hành vi liên quan vào cùng một Class là một trong những đặc điểm cơ bản của lập trình hướng đối tượng.
- Constructor là gì?
Constructor là một phương thức đặc biệt được sử dụng để khởi tạo Object.
Khi một Object được tạo ra, Constructor được gọi để thiết lập những giá trị ban đầu cho Object.
Constructor trong Dart thường có tên giống với Class.
Ví dụ:
class Student {
String name;
int age;
Student(this.name, this.age);
}
Student(this.name, this.age) là Constructor.
Khi tạo Object, các giá trị được truyền vào Constructor sẽ được sử dụng để khởi tạo dữ liệu cho Object.
Constructor rất quan trọng vì trong các ứng dụng thực tế, Object thường cần có dữ liệu ngay từ thời điểm được tạo ra.
- Từ khóa this
this dùng để tham chiếu đến Object hiện tại.
Nó thường được sử dụng trong Constructor hoặc Method khi cần phân biệt thuộc tính của Object với tham số hoặc biến cục bộ có cùng tên.
Ví dụ:
Student(this.name, this.age);
Ở đây this.name và this.age đại diện cho thuộc tính name và age của Object hiện tại.
Trong Dart, cách viết này rất phổ biến vì ngắn gọn và dễ đọc.
- Named Constructor
Dart cho phép một Class có nhiều cách khởi tạo Object thông qua Named Constructor.
Named Constructor là Constructor có thêm tên phía sau tên Class.
Mục đích của Named Constructor là cung cấp nhiều cách khác nhau để tạo Object tùy theo trường hợp sử dụng.
Ví dụ một Class có thể có Constructor thông thường để tạo User bình thường và một Named Constructor để tạo User khách.
Điều này giúp Class linh hoạt hơn khi khởi tạo Object.
- Factory Constructor
Factory Constructor là một dạng Constructor đặc biệt trong Dart.
Khác với Constructor thông thường, Factory Constructor có thể kiểm soát quá trình tạo Object và quyết định Object nào sẽ được trả về.
Factory Constructor có thể được sử dụng trong những trường hợp như:
- Tạo Object theo điều kiện.
- Trả về một Object đã tồn tại.
- Chuyển dữ liệu thành Object.
- Xử lý việc khởi tạo phức tạp.
Factory Constructor thường xuất hiện trong các Model, thư viện và kiến trúc ứng dụng Dart/Flutter thực tế.
Bạn chưa cần quá tập trung vào phần này ở giai đoạn đầu, nhưng nên hiểu khái niệm và biết cách nhận ra nó khi đọc code.
- Encapsulation – Tính đóng gói
Encapsulation hay tính đóng gói là một trong bốn tính chất quan trọng của OOP.
Đóng gói nghĩa là gom dữ liệu và các phương thức xử lý dữ liệu vào trong một Class, đồng thời kiểm soát cách các thành phần bên ngoài truy cập vào dữ liệu đó.
Mục đích của Encapsulation là:
- Bảo vệ dữ liệu.
- Hạn chế việc thay đổi dữ liệu không hợp lệ.
- Kiểm soát cách dữ liệu được truy cập.
- Giúp Class dễ quản lý hơn.
Trong Dart, tên bắt đầu bằng dấu _ được xem là private trong phạm vi Library.
Ví dụ:
double _balance = 0;
Dấu _ cho biết thành phần này không nên được truy cập trực tiếp từ bên ngoài Library.
Đóng gói không đơn giản chỉ là “ẩn biến”. Quan trọng hơn, nó giúp Class kiểm soát cách dữ liệu được sử dụng.
- Getter là gì?
Getter là cơ chế dùng để lấy dữ liệu từ một Object.
Getter thường được sử dụng khi một thuộc tính được đóng gói và không muốn cho bên ngoài truy cập trực tiếp vào biến bên trong.
Ví dụ:
String get name => _name;
Khi đó bên ngoài có thể lấy giá trị thông qua name thay vì truy cập trực tiếp _name.
Getter thường được sử dụng cùng với Encapsulation.
- Setter là gì?
Setter là cơ chế dùng để thay đổi giá trị của một thuộc tính.
Setter cho phép Class kiểm soát dữ liệu trước khi thay đổi.
Ví dụ, thay vì cho phép bên ngoài thay đổi trực tiếp số dư tài khoản, Class có thể kiểm tra xem giá trị mới có hợp lệ hay không trước khi cập nhật.
Setter thường được sử dụng khi muốn kiểm soát việc ghi dữ liệu.
- Có thể hiểu đơn giản:
- Getter → đọc dữ liệu
- Setter → thay đổi dữ liệu
- Static là gì?
static dùng để khai báo thành phần thuộc về Class, thay vì thuộc về từng Object.
Thông thường, mỗi Object sẽ có dữ liệu riêng.
Nhưng với static, dữ liệu hoặc Method được chia sẻ ở cấp Class.
Static thường được sử dụng cho:
- Hằng số dùng chung.
- Các hàm tiện ích.
- Dữ liệu chung cho tất cả Object.
- Các chức năng không cần tạo Object để sử dụng.
Ví dụ:
class MathUtils {
static int add(int a, int b) {
return a + b;
}
}
Có thể gọi trực tiếp thông qua Class mà không cần tạo Object.
- Inheritance – Tính kế thừa
Inheritance hay tính kế thừa là một trong bốn tính chất quan trọng của OOP.
Kế thừa cho phép một Class mới sử dụng lại những đặc điểm và hành vi của một Class đã có.
Class được kế thừa thường được gọi là Class cha, còn Class kế thừa được gọi là Class con.
Trong Dart, kế thừa được thực hiện bằng từ khóa: extends
Ví dụ:
class Dog extends Animal {
}
Điều này có nghĩa Dog kế thừa từ Animal.
Kế thừa giúp:
- Tái sử dụng code.
- Hạn chế việc viết lại code.
- Xây dựng mối quan hệ giữa các Class.
- Dễ mở rộng chương trình.
Tuy nhiên, không phải lúc nào cũng nên sử dụng kế thừa. Trong các hệ thống lớn, lập trình viên thường cân nhắc giữa Inheritance và Composition.
- super là gì?
super được sử dụng để tham chiếu đến Class cha.
Nó thường được sử dụng để:
- Gọi Constructor của Class cha.
- Gọi Method của Class cha.
- Truy cập thuộc tính của Class cha.
Ví dụ:
class Dog extends Animal {
Dog(String name) : super(name);
}
Ở đây super(name) gọi Constructor của Class cha.
Khi đọc code Flutter, bạn sẽ gặp super khá thường xuyên, đặc biệt trong Constructor của Widget.
- Method Overriding
Overriding là việc Class con viết lại cách hoạt động của một Method đã được định nghĩa ở Class cha.
Trong Dart, @override được sử dụng để đánh dấu Method đang được ghi đè.
Ví dụ:
@override
void sound() {
print("Gâu gâu");
}
Overriding cho phép Class con thay đổi hành vi của Class cha sao cho phù hợp với mục đích của Class con.
Đây là cơ chế quan trọng để thực hiện Polymorphism.
- Polymorphism – Tính đa hình
Polymorphism hay tính đa hình là một trong bốn tính chất quan trọng của OOP.
Đa hình cho phép các Object thuộc những Class khác nhau có thể được xử lý thông qua một kiểu chung nhưng mỗi Object có thể thực hiện hành vi theo cách riêng.
Nói đơn giản, cùng một Method nhưng các Class khác nhau có thể có cách thực hiện khác nhau.
Ví dụ:
Animal
├── Dog → sound() → Gâu gâu
└── Cat → sound() → Meo meo
Cả Dog và Cat đều có sound() nhưng kết quả khác nhau.
Đa hình giúp chương trình linh hoạt hơn và giảm sự phụ thuộc vào một Class cụ thể.
- Abstraction – Tính trừu tượng
Abstraction hay tính trừu tượng là một trong bốn tính chất quan trọng của OOP.
Trừu tượng có nghĩa là chỉ tập trung vào những đặc điểm cần thiết và ẩn đi những chi tiết triển khai không cần thiết đối với người sử dụng.
Ví dụ, khi sử dụng một chiếc điện thoại, người dùng chỉ cần biết cách gọi điện, nhắn tin hoặc mở ứng dụng. Người dùng không cần biết toàn bộ quá trình xử lý bên trong điện thoại.
Trong lập trình cũng tương tự. Một Class có thể cung cấp những Method cần thiết nhưng che giấu cách các Method đó hoạt động bên trong.
Dart hỗ trợ Abstraction thông qua abstract class.
Ví dụ:
abstract class Animal {
void sound();
}
Class trừu tượng thường được dùng để định nghĩa một cấu trúc chung cho các Class khác triển khai.
- Abstract Class
abstract class là Class trừu tượng.
Abstract Class thường được sử dụng để tạo ra một cấu trúc hoặc quy tắc chung cho các Class con.
Một Abstract Class có thể chứa:
- Thuộc tính.
- Method đã có phần triển khai.
- Method chưa có phần triển khai.
Không thể tạo Object trực tiếp từ Abstract Class.
Ví dụ:
abstract class Animal {
void sound();
}
Class Animal chỉ đưa ra yêu cầu rằng các Class phù hợp phải có sound(). Cách sound() hoạt động sẽ do Class cụ thể quyết định.
- Interface và implements
Trong Dart, mỗi Class đều có thể được sử dụng như một Interface.
Interface có thể hiểu là một bộ quy tắc mà Class khác phải tuân theo.
Từ khóa implements được sử dụng khi một Class muốn triển khai một Interface.
Ví dụ:
class Dog implements Animal {
}
Khi sử dụng implements, Class thực hiện phải tự triển khai những Method mà Interface yêu cầu.
Điểm cần nhớ:
extends → kế thừa
implements → tuân theo Interface
extends tập trung vào việc tái sử dụng cấu trúc và hành vi của Class cha, trong khi implements tập trung vào việc đảm bảo Class đáp ứng một cấu trúc hoặc hợp đồng nhất định.
- Mixin
Mixin là một cơ chế đặc biệt của Dart cho phép tái sử dụng hành vi giữa nhiều Class mà không cần sử dụng kế thừa trực tiếp.
Mixin được khai báo bằng từ khóa mixin và thường được sử dụng bằng with.
Ví dụ:
mixin Flyable {
void fly() {
print("Đang bay");
}
}
Một Class có thể sử dụng Mixin này để có thêm hành vi fly().
Mixin hữu ích khi nhiều Class khác nhau cần cùng một hành vi nhưng những Class đó không nhất thiết phải có quan hệ kế thừa với nhau.
- Composition – Kết hợp đối tượng
Composition là một cách thiết kế trong OOP, trong đó một Class sử dụng hoặc chứa Object của Class khác thay vì kế thừa trực tiếp.
Có thể hiểu đơn giản:
Inheritance → "là một"
Composition → "có một"
Ví dụ:
Dog là một Animal
Car có một Engine
Composition giúp xây dựng chương trình linh hoạt vì một Class có thể sử dụng nhiều Object khác nhau mà không cần tạo ra hệ thống kế thừa phức tạp.
Trong các dự án thực tế, đặc biệt là các dự án có kiến trúc lớn, Composition thường được sử dụng rất nhiều.
- Null Safety trong Dart OOP
Null Safety là cơ chế của Dart giúp hạn chế lỗi xảy ra khi một biến không có giá trị.
Trong Dart, mặc định một biến không được phép nhận null.
Ví dụ:
String name;
name phải có giá trị String.
Nếu muốn cho phép null, sử dụng dấu ?:
String? name;
Điều này đặc biệt quan trọng khi xây dựng Model trong Flutter vì dữ liệu lấy từ API hoặc Database có thể thiếu một số trường.
Null Safety giúp lập trình viên phát hiện và xử lý những trường hợp có thể xảy ra null ngay trong quá trình viết code.
- Named Parameters và required
Dart thường sử dụng Named Parameters khi làm việc với Constructor.
Ví dụ:
class Product {
Product({
required this.name,
required this.price,
});
String name;
double price;
}
required có nghĩa là tham số bắt buộc phải được truyền vào khi tạo Object.
Named Parameters giúp code dễ đọc hơn vì tên của từng giá trị được thể hiện rõ ràng.
Đây là cách viết xuất hiện rất thường xuyên trong Flutter.
- OOP trong Flutter
Dart OOP có vai trò rất lớn trong Flutter.
Flutter sử dụng Class để xây dựng rất nhiều thành phần của ứng dụng.
Ví dụ:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text("Hello Flutter");
}
}
Trong đoạn code này:
- MyApp là một Class.
- extends StatelessWidget là kế thừa.
- @override là ghi đè Method.
- build() là Method.
- super thường xuất hiện trong Constructor của Widget.
Ngoài Widget, OOP còn được sử dụng trong:
- Model.
- Service.
- Repository.
- API Client.
- State Management.
- Database.
- Các lớp xử lý nghiệp vụ.
Vì vậy, nếu chưa hiểu OOP thì khi đọc code Flutter sẽ rất dễ gặp tình trạng nhìn thấy nhiều class, extends, implements, override, abstract, mixin nhưng không hiểu chúng dùng để làm gì.
- Bốn tính chất quan trọng nhất của OOP
Trong Dart OOP, cần đặc biệt nhớ bốn tính chất chính:
- Encapsulation – Đóng gói
- Đóng gói dữ liệu và hành vi vào Class, đồng thời kiểm soát quyền truy cập.
- Mục đích: bảo vệ và kiểm soát dữ liệu.
- Inheritance – Kế thừa
- Class con có thể kế thừa từ Class cha.
- Mục đích: tái sử dụng code.
- Polymorphism – Đa hình
- Các Class khác nhau có thể có cùng một Method nhưng cách thực hiện khác nhau.
- Mục đích: giúp chương trình linh hoạt.
- Abstraction – Trừu tượng
- Ẩn những chi tiết không cần thiết và chỉ cung cấp những gì cần thiết.
- Mục đích: giảm độ phức tạp và tạo cấu trúc rõ ràng.
Có thể ghi nhớ nhanh:
- Đóng gói → bảo vệ dữ liệu
- Kế thừa → tái sử dụng
- Đa hình → linh hoạt
- Trừu tượng → ẩn chi tiết
- Các từ khóa Dart OOP cần nhớ
Sau khi học Dart OOP, bạn nên nhận biết được những từ khóa và khái niệm sau:
- class
- object
- this
- constructor
- named constructor
- factory
- static
- get
- set
- extends
- super
- @override
- abstract
- implements
- mixin
- with
- required
Không cần học thuộc lòng tất cả ngay lập tức. Quan trọng nhất là khi nhìn thấy chúng trong code phải biết chúng có mục đích gì và tại sao lập trình viên sử dụng chúng.
- Thứ tự nên học Dart OOP
Để tránh học lan man, có thể học theo thứ tự:
Class → Object → Field → Method → Constructor → this → Named Constructor → Encapsulation → Getter/Setter → Inheritance → extends → super → Override → Polymorphism → Abstraction → abstract class → Interface → implements → Mixin → Composition → Static → Null Safety → Named Parameters → Factory Constructor
Trong đó, những phần nên hiểu thật chắc trước khi đi vào Flutter là:
Class → Object → Constructor → Encapsulation → Inheritance → Override → Polymorphism → Abstraction
Sau đó học tiếp:
implements → Mixin → Composition → Factory Constructor → Static
- Kết luận
Dart OOP là kiến thức nền tảng của ngôn ngữ Dart và có vai trò rất quan trọng trong quá trình phát triển ứng dụng Flutter.
Thông qua OOP, chương trình được tổ chức thành các Class và Object. Class mô tả dữ liệu và hành vi, còn Object là những đối tượng cụ thể được tạo ra từ Class.
Những kiến thức quan trọng nhất của Dart OOP gồm Class, Object, Constructor, Encapsulation, Inheritance, Polymorphism và Abstraction. Bên cạnh đó, khi làm việc với Dart và Flutter thực tế cần tiếp tục hiểu extends, implements, abstract, override, super, Getter/Setter, Mixin, Composition, Static, Factory Constructor và Null Safety.
Mục tiêu của việc học Dart OOP không phải là học thuộc định nghĩa mà là hiểu được cấu trúc của code và lý do tại sao lập trình viên tổ chức code theo cách đó. Khi đã hiểu OOP, việc đọc code Flutter sẽ dễ dàng hơn vì có thể nhận biết được Class nào đang được tạo, Class nào đang kế thừa, Method nào đang được ghi đè và các đối tượng đang liên kết với nhau như thế nào.
Đối đối với quá trình học Flutter để tham gia dự án thực tế, Dart OOP là một phần kiến thức nền tảng cần nắm chắc trước khi đi sâu vào Widget, State Management, API, Database và Architecture.




Khoá học lập trình game con rắn cho trẻ em




