TypeScript cơ bản cho tester (P4): OOP, class và object

⏱︎

Read time:

4–6 minutes
Minh họa class tạo ra nhiều object trong lập trình hướng đối tượng

Ở các phần trước, chúng ta đã dùng biến, object, function và class ở mức cơ bản. Bài này đi sâu hơn một bước: tổ chức dữ liệu và hành vi bằng lập trình hướng đối tượng (Object-Oriented Programming – OOP). Mục tiêu là đọc hiểu và tự viết được những class nhỏ thường gặp trong project automation.

Lưu ý
Bài này chưa sử dụng Page Object Model hay Playwright. Hãy hiểu class và object trước; khi học POM sau này, bạn sẽ thấy đó chỉ là một cách ứng dụng các khái niệm OOP này.

OOP là gì?

OOP là cách tổ chức chương trình xoay quanh các object. Mỗi object thường chứa hai nhóm thông tin:

Ví dụ với 1 đối tượng Nguyễn Văn A thì sẽ có:

  • Thuộc tính: tên, tuổi, địa chỉ, giới tính…
  • Hành vi: ăn, ngủ, chơi…

Ở ví dụ trên, Nguyễn Văn A là 1 object của class Human

Khái niệmHiểu đơn giảnVí dụ
ClassBản thiết kế để tạo ra các đối tượngHuman
ObjectMột đối tượng được tạo từ bản thiết kếNguyễn Văn A
PropertyDữ liệu của objectname, age, address
MethodHành vi của objecteat(), sleep(), wakeUp()

Class và object

Một class mô tả object sẽ có dữ liệu gì và làm được gì. Khi dùng từ khóa new, TypeScript tạo ra một object cụ thể từ class đó.

class TestCase {
  name: string;
  priority: string;

  constructor(name: string, priority: string) {
    this.name = name;   //gán param name vào property name ở bên trên của class
    this.priority = priority;   //tương tự
  }

  run(): void {
    console.log("Running: " + this.name + " [" + this.priority + "]");
  }
}

const loginTest = new TestCase("Login successfully", "High");
loginTest.run();

Trong ví dụ trên, TestCase là class; loginTest là object. Hai property name và priority lưu dữ liệu, còn run() là method mô tả hành vi.

Constructor dùng để khởi tạo object

constructor chạy tự động mỗi khi chúng ta gọi new TestCase(...). Nó nhận dữ liệu ban đầu và gán dữ liệu đó cho object.

Mẹo nhớ
Constructor hiểu đơn giản là 1 hàm để build lên được cái object đó từ những tham số cần thiết

TypeScript có cú pháp rút gọn: thêm access modifier ngay trước parameter trong constructor. Trình biên dịch sẽ tự tạo property và gán giá trị, giúp giảm code lặp. Ví dụ dưới đây bạn có thể thấy không cần khai báo properties cho class này, khai báo trực tiếp luôn trong constructor:

class TestUser {
  constructor(
    public email: string,
    public role: string,
    public isActive: boolean = true,
  ) {}
}

const student = new TestUser("student@elitest.vn", "student");
console.log(student.email);
console.log(student.isActive);

this là object hiện tại

Bên trong class, this trỏ tới object đang gọi method. Vì vậy cùng một method nhưng có thể thao tác với dữ liệu khác nhau của từng object.

class Person {
  constructor(public name: string) {}

  introduce(): void {
    console.log("Mình là " + this.name);
  }
}

const linh = new Person("Linh");
const an = new Person("An");

linh.introduce(); // this là object linh
an.introduce();   // this là object an

Một class có thể tạo nhiều object

Class chỉ cần định nghĩa một lần nhưng có thể tạo bao nhiêu object tùy ý. Mỗi object giữ state riêng; cập nhật object này không tự động làm thay đổi object khác.

class PiggyBank {
  balance: number = 0;

  constructor(public owner: string) {}

  addMoney(amount: number): void {
    this.balance += amount;
  }
}

const linhPiggyBank = new PiggyBank("Linh");
const anPiggyBank = new PiggyBank("An");

linhPiggyBank.addMoney(100_000);
anPiggyBank.addMoney(50_000);

console.log(linhPiggyBank.balance); // 100000
console.log(anPiggyBank.balance);   // 50000

Class quản lý một nhóm object

OOP không chỉ dùng để mô tả từng object riêng lẻ. Một class có thể quản lý danh sách object khác, ví dụ một test suite chứa nhiều test case.

class TestCase {
  constructor(
    public name: string,
    public status: "Passed" | "Failed",
  ) {}
}

class TestSuite {
  private testCases: TestCase[] = [];

  add(testCase: TestCase): void {
    this.testCases.push(testCase);
  }

  countFailed(): number {
    return this.testCases.filter(
      (testCase) => testCase.status === "Failed",
    ).length;
  }
}

const smokeSuite = new TestSuite();
smokeSuite.add(new TestCase("Login", "Passed"));
smokeSuite.add(new TestCase("Create article", "Failed"));

console.log(smokeSuite.countFailed()); // 1

Bài tập nhỏ

  1. Tạo class Student có name, email và isActive.
  2. Dùng constructor để nhận name và email; isActive mặc định là true.
  3. Thêm method deactivate() để chuyển isActive thành false.
  4. Tạo hai object và kiểm tra state của chúng độc lập với nhau.

Tóm tắt

  • Class là bản thiết kế; object là đối tượng cụ thể được tạo từ class.
  • Property lưu dữ liệu; method mô tả hành vi.
  • Constructor khởi tạo dữ liệu khi tạo object.
  • this trỏ tới object đang thực thi method.
  • Một class có thể tạo nhiều object, mỗi object là độc lập với nhau