Object Oriented-Programming in C++
Object-Oriented-Programming (Object-Oriented-Programming) is an object-based programming method to find out the nature of the problem. This course helps programmers learn programming techniques that all logic and practical requirements are built around objects. Understanding how OOP works in C++ will simplify maintenance and scalability in software development.
Vậy lập trình hướng đối tượng là gì?

1. Tính đóng gói (Encapsulation)

Các lợi ích chính mà tính đóng gói đem lại:
- Hạn chế được các truy xuất không hợp lệ tới các thuộc tính của đối tượng.
- Giúp cho trạng thái của các đối tượng luôn đúng. Ví dụ nếu thuộc tính
gpa
của lớpStudent
làpublic
thì sẽ rất khó kiểm soát được giá trị, bạn có thể thay đổigpa
thành bất kỳ giá trị nào. Ngược lại, nếu bạn để thuộc tínhgpa
làprivate
và cung cấp hàmsetGpa()
giống như sau:
void setGpa(double gpa) {
if (gpa >= 0 && gpa <= 4) {
this->gpa = gpa;
} else {
cout << "gpa is invalid";
}
}
thì lúc này giá trị của thuộc tính gpa
sẽ luôn được đảm bảo là không âm và nhỏ hơn hoặc bằng 4
(do muốn thay đổi gpa
thì phải thông qua hàm setGpa()
).
- Giúp ẩn đi những thông tin không cần thiết về đối tượng.
- Cho phép bạn thay đổi cấu trúc bên trong lớp mà không ảnh hưởng tới lớp khác. Ví dụ ban đầu bạn thiết kế lớp
Student
giống như sau:
class Student {
private:
string firstName;
string lastName;
public:
Student() {
...
}
string getFullName() {
return firstName + lastName;
}
};
Sau này nếu bạn muốn gộp 2 thuộc tính firstName
và lastName
thành fullName
thì lớp Student
sẽ giống như sau:
class Student {
private:
string fullName;
public:
Student() {
...
}
string getFullName() {
return fullName;
}
};
Lúc này cấu trúc lớp Student
đã bị thay đổi nhưng các đối tượng sử dụng lớp này vẫn không cần phải thay đổi do các đối tượng này chỉ quan tâm tới phương thức getFullName()
. Nếu không có phương thức này thì bạn phải sửa tất cả những chỗ sử dụng thuộc tính firstName
và lastName
của lớp Student
.
Lưu ý: hãy luôn nhớ rằng mục đích chính của tính đóng gói là để hạn chế các lỗi khi phát triển chương trình chứ không phải là bảo mật hay che giấu thông tin.
2. Tính kế thừa (Inheritance)
Person
và cho lớp Student
và Teacher
kế thừa lớp này giống như sau:Student
và Teacher
sẽ được thừa hưởng lại các thuộc tính chung từ lớp Person
và code sẽ không còn bị trùng lặp. Đó chính là lợi ích của tính kế thừa.3. Tính đa hình (Polymorphism)
3.1. Đa hình với nạp chồng phương thức
Ví dụ: phương thức cộng sẽ có các hình thái là cộng 2 số nguyên, cộng 2 số thực, cộng 3 số nguyên, v/v. Có thể thấy cùng là phương thức cộng nhưng lại có nhiều hình thái khác nhau nên đây chính là biểu hiện của tính đa hình. Ví dụ về đa hình với nạp chồng phương thức:
#include <iostream>
using namespace std;
class Calculator {
public:
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
};
int main() {
Calculator c;
cout << c.add(1, 2) << endl;
cout << c.add(3.3, 4.2) << endl;
cout << c.add(1, 2, 3) << endl;
return 0;
}
Kết quả khi chạy chương trình:
3
7.5
6
3.2. Đa hình với ghi đè phương thức
Ví dụ phương thức getSalary()
dùng để tính lương sẽ có các hình thái là tính lương cho quản lý, tính lương cho nhân viên:
class Employee {
private:
string name;
int salary;
public:
Employee(string name, int salary) {
this->name = name;
this->salary = salary;
}
string getName() {
return name;
}
void setName(string name) {
this->name = name;
}
int getSalary() {
return salary;
}
void setSalary(int salary) {
this->salary = salary;
}
void display() {
cout << "Name: " << getName() << endl;
cout << "Salary: " << getSalary() << endl;
}
};
class Manager : Employee {
private:
int bonus;
public:
Manager(string name, int salary, int bonus) : Employee(name, salary) {
this->bonus = bonus;
}
int getBonus() {
return bonus;
}
void setBonus(int bonus) {
this->bonus = bonus;
}
int getSalary() {
return Employee::getSalary() + bonus;
}
};
Đều là tính lương nhưng với mỗi đối tượng lại có một cách tính khác nhau, đó chính là tính đa hình.
3.3 Đa hình thông qua các đối tượng đa hình (polymorphic objects)
Biến thuộc lớp cha có thể tham chiếu tới đối tượng của các lớp con, vậy biến thuộc lớp cha cũng có nhiều hình thái nên đây cũng là đa hình. Ví dụ:
#include <iostream>
using namespace std;
class Animal {
public:
virtual void sound() {
cout << "some sound" << endl;
}
};
class Dog : public Animal {
public:
void sound() {
cout << "bow wow" << endl;
}
};
class Cat : public Animal {
public:
void sound() {
cout << "meow meow" << endl;
}
};
class Duck : public Animal {
public:
void sound() {
cout << "quack quack" << endl;
}
};
int main() {
Animal* animal = new Animal();
animal->sound();
animal = new Dog();
animal->sound();
animal = new Duck();
animal->sound();
animal = new Cat();
animal->sound();
return 0;
}
Kết quả khi chạy chương trình:
some sound
bow wow
quack quack
meow meow
4.Tính trừu tượng (Abstraction)
Khi bạn đi rút tiền ở cây ATM thì bạn không cần quan tâm tới cách mà cây ATM hoạt động hay các thành phần có trong cây ATM, cái mà bạn quan tâm duy nhất đó là tính năng rút tiền. Trong trường hợp này các thông tin không cần thiết của cây ATM như đếm tiền, trừ tiền trong tài khoản, gửi dữ liệu về máy chủ đã được ẩn đi. Cái mà bạn nhìn thấy về đối tượng cây ATM chính là rút tiền => cây ATM đã ẩn đi những chi tiết không cần thiết và đó chính là tính trừu tượng.
Tương tự trong lập trình cũng vậy, khi gọi tới các phương thức của một đối tượng thì bạn chỉ cần quan tâm tới phương thức đó được dùng để làm gì chứ không cần quan tâm tới phương thức đó được code như thế nào. Tính chất này rất có ích khi làm việc nhóm, bạn chỉ cần quan tâm tới chức năng của các phương thức mà đồng nghiệp code chứ không cần biết nó được cài đặt như thế nào. Để thực hiện tính trừu tượng thì bạn có thể sử dụng các abstract class và interface vì nó chỉ chứa phần khai báo chứ không có phần cài đặt (ở một số ngôn ngữ không có khái niệm về interface nên nếu bạn chưa biết về interface thì có thể hiểu interface chính là abstract class với các phương thức đều là trừu tượng).