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

Tính đóng gói (Encapsulation) là tính chất theo hướng bảo mật trong lập trình hướng đối tượng, tính chất này sẽ là một quy tắc yêu cầu trạng thái bên trong của một đối tượng được bảo vệ và tránh truy cập được từ các đối tượng hay đoạn mã truy cập ở bên ngoài lớp đó. Việc đóng gọi nghĩa là tránh các đoạn mã bên ngoài không thể nhìn thấy và thay đổi trạng thái của đối tượng đó.

Một lớp cũng được coi là đóng gói, khi đó lớp sẽ đóng gói tất cả dữ liệu của các thuộc tính và phương thức có trong nó. Hình ảnh dưới đây miêu tả tính đóng gói của một lớp đối với các thuộc tính và phương thức có trong lớp đó:

Người lập trình có thể sử dụng tính đóng gói cho mục đích bảo vệ dữ liệu bên trong của đối tượng. Khi các dữ liệu đã được đóng gói thì việc truy cập hay chỉnh sửa sẽ không thể thực hiện được ở bên ngoài đối tượng.

2. Phạm vi Protected trong Python

Phạm vi Protected trong một đối tượng là không gian mà các thuộc tính và các phương thức có thể được thực hiện trong chương trình. Khi các thuộc tính và phương thức thuộc phạm vi Protected thì chúng không thể được truy cập bên ngoài lớp nhưng có thể được truy cập từ bên trong lớp và các lớp con kế thừa của lớp đó.

Để khai báo một thành phần trong lớp thuộc phạm vi protected thì ta cần tuân theo quy tắc thêm ký tự ” _” (gạch dưới) vào trước tên của thành phần đó.

Ví dụ dưới đây, khai báo một lớp ConNguoi bao gồm các thuộc tính _HoTen, _Tuoi, _GioiTinh và các phương thức _an(), _noi(), _hoc() trong phạm vi Protected, các thuộc tính này chỉ được phép truy cập và sử dụng ở trong lớp ConNguoi và các lớp con kế thừa lớp ConNguoi

class ConNguoi:
    # Khai bao thuoc tinh Protected
    _HoTen = "Chu Minh Nam"
    _Tuoi = 20
    _GioiTinh = "nam"
    # Khai bao phuong thuc Protected
    def _an(self):
        print("{0} co the an!".format(self._HoTen))
    def _noi(self):
        print("{0} co the noi!".format(self._HoTen))
    def _hoc(self):
        print("{0} co the hoc!".format(self._HoTen))

# Khai bao lop SinhVien ke thua lop ConNguoi
class SinhVien(ConNguoi):
    MaSinhVien = 202103102
    DiemTongKet = 9.5
    XepLoai = "gioi"

# Khoi tao doi tuong p1 tu lop ConNguoi
p1 = ConNguoi()
# Truy cap thuoc tinh va phuong thuc Protected tu doi tuong p1
print(p1._HoTen)
print(p1._Tuoi)
print(p1._GioiTinh)
p1._an()
p1._noi()
p1._hoc()
print("\n")

# Khoi tao doi tuong sv1 tu lop SinhVien
sv1 = SinhVien()
# Truy cap thuoc tinh va phuong thuc Protected tu doi tuong sv1
print("Ho Ten SV: {0}".format(sv1._HoTen))
print("Tuoi SV: {0}".format(sv1._Tuoi))
print("Gioi Tinh SV: {0}".format(sv1._GioiTinh))
sv1._an()
sv1._noi()
sv1._hoc()

Kết quả:

Chu Minh Nam
20
nam
Chu Minh Nam co the an!
Chu Minh Nam co the noi!
Chu Minh Nam co the hoc!

Ho Ten SV: Chu Minh Nam
Tuoi SV: 20
Gioi Tinh SV: nam
Chu Minh Nam co the an!
Chu Minh Nam co the noi!
Chu Minh Nam co the hoc!

Trong ví dụ trên, các thuộc tính và phương thức trong lớp ConNguoi được khai báo trong phạm vi Protected thông qua cách thêm ký tự “_” vào trước tên thuộc tính và phương thức đó. Lớp khi khai báo đối tượng p1 có thể gọi các thuộc tính và phương thức trong lớp ConNguoi ra ngoài và thực thi. Do lớp SinhVien kế thừa lớp ConNguoi nên khi truy cập vào các thuộc tính và phương thức Protected thông qua đối tượng sv1 là hoàn toàn hợp lệ!

3. Phạm vi Private trong Python

Phạm vi Private trong một đối tượng cũng được hiểu tương tự như phạm vị Protected đó là việc các thành phần có thể được truy cập trong lớp đó, thế nhưng đặc điểm nổi bật của của phạm vi Private đó là các thành phần của lớp được khai báo là Private sẽ không được truy cập bên ngoài lớp và cũng không thể truy cập các thành phần này bên trong các lớp con kế thừa.

Để khai báo một thành phần trong lớp thuộc phạm vi Private thì ta cần tuân theo quy tắc thêm ký tự ” __” (2 gạch dưới) vào trước tên của thành phần đó.

Ví dụ dưới đây, khai báo một lớp ConNguoi bao gồm các thuộc tính __HoTen, __Tuoi, __GioiTinh và các phương thức __an(), __noi(), __hoc() trong phạm vi Private, các thuộc tính này chỉ được phép truy cập và sử dụng ở trong lớp ConNguoi các lớp kế thừa và các cách gọi bên ngoài lớp ConNguoi sẽ không thể truy cập vào các thành phần thuộc phạm vi Private.

class ConNguoi:
    # Khai bao thuoc tinh Private
    __HoTen = "Chu Minh Nam"
    __Tuoi = 20
    __GioiTinh = "nam"
    # Khai bao phuong thuc Private
    def __an(self):
        print("{0} co the an!".format(self._HoTen))
    def __noi(self):
        print("{0} co the noi!".format(self._HoTen))
    def __hoc(self):
        print("{0} co the hoc!".format(self._HoTen))

# Khai bao lop SinhVien ke thua lop ConNguoi
class SinhVien(ConNguoi):
    MaSinhVien = 202103102
    DiemTongKet = 9.5
    XepLoai = "gioi"

# Khoi tao doi tuong p1 tu lop ConNguoi
p1 = ConNguoi()
# Truy cap thuoc tinh va phuong thuc Private tu doi tuong p1
print(p1.__HoTen)
print(p1.__Tuoi)
print(p1.__GioiTinh)
p1.__an()
p1.__noi()
p1.__hoc()
print("\n")

# Khoi tao doi tuong sv1 tu lop SinhVien
sv1 = SinhVien()
# Truy cap thuoc tinh va phuong thuc Private tu doi tuong sv1
print("Ho Ten SV: {0}".format(sv1.__HoTen))
print("Tuoi SV: {0}".format(sv1.__Tuoi))
print("Gioi Tinh SV: {0}".format(sv1.__GioiTinh))
sv1.__an()
sv1.__noi()
sv1.__hoc()

Kết quả:

Traceback (most recent call last):
  File "d:\laptrinhtudau\python\main.py", line 23, in <module>
    print(p1.__HoTen)
AttributeError: 'ConNguoi' object has no attribute '__HoTen'

Vì trong lớp ConNguoi các thành phần đều thuộc phạm vi Private và không thể được phép truy cập từ bên ngoài lớp ConNguoi cũng như truy cập thông qua các lớp con kế thừa. Vì vậy, khi cố tình truy cập vào các thành phần có phạm vi Private bằng các đối tượng p1sv1 chương trình trên sẽ gây ra lỗi.