1. Tính đóng gói (encapsulation) trong Python
Tính đóng gói (encapsulation) là một trong những tính chất quan trọng của lập trình hướng đối tượng (object-oriented programming). Đó là việc thiết kế để các thuộc tính và phương thức thuộc về (bên trong) một lớp. Tính đóng gói sẽ giúp ngăn chặn việc truy cập, thay đổi thuộc tính và phương thức của một lớp một cách trực tiếp. Từ đó, giúp cho việc che giấu dữ liệu (data hiding).
Python thể hiện tính đóng gói thông qua việc chỉ định các thuộc tính và phương thức ở chế độ private. Các thuộc tính và phương thức private chỉ có thể được truy cập, sử dụng bên trong lớp chứa nó. Python sử dụng dấu gạch dưới _ hoặc __ làm tiền tố (prefix) để chỉ định một thuộc tính hoặc một phương thức là private.
class Person:
def __init__(self):
self.__age = 20
def showAge(self):
print(self.__age)
def setAge(self, age):
self.__age = age
david = Person()
print("Age of david: ", end='')
david.showAge()
david.__age = 99
print("Age of david after david.__age = 99: ", end='')
david.showAge()
david.setAge(99)
print("Age of david after david.setAge(99): ", end='')
david.showAge()
Kết quả
Age of david: 20
Age of david after david.__age = 99: 20
Age of david after david.setAge(99): 99
Trong ví dụ trên, chúng ta định nghĩa một lớp Person. Lớp Person có thuộc tính private __age. Khi chúng ta thay đổi biến này bên ngoài david.__age = 99
, thì nó sẽ không được thay đổi bên trong đối tượng david của lớp Person. Giá trị của biến __age của đối tượng david sẽ được thay đổi với hàm setAge()
.
Các thuộc tính và phương thức private sẽ không thể được sử dụng bên ngoài lớp chứa chúng.
class Person:
def __init__(self):
self.__age = 20
def showAge(self):
print(self.__age)
def setAge(self, age):
self.__age = age
# private method
def __info():
print("Info of a person.")
david = Person()
# AttributeError: 'Person' object has no attribute '__age'
print(david.__age)
# AttributeError: 'Person' object has no attribute '__info'
david.__info()
2. Tính đa hình (polymorphism) trong Python
Tính đa hình (polymorphism) hiểu đơn giản là các đối tượng, các phương thức giống nhau có thể có các hành vi khác nhau tùy vào từng tình huống khác nhau.
class Vietnam():
def capital(self):
print("capital: Ha Noi")
def language(self):
print("language: Vietnamese")
class Japan():
def capital(self):
print("capital: Tokyo")
def language(self):
print("language: Japanese")
# common method
def aboutCountry(country):
country.capital()
country.language()
# create objects
vn = Vietnam()
jp = Japan()
# passing the object
print("about Vietnam")
aboutCountry(vn)
print("about Japan")
aboutCountry(jp)
Kết quả
about Vietnam
capital: Ha Noi
language: Vietnamese
about Japan
capital: Tokyo
language: Japanese
Trong ví dụ trên, lớp Vietnam và Japan đều có các hàm capital()
và language()
. Nhưng chúng sẽ cho kết quả khác nhau khi được gọi đến thông qua hàm aboutCountry()
.
Ghi đè (overriding) phương thức khi kế thừa cũng là một thể hiện của tính đa hình.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print(self.name + ",", self.age, "years old.")
class Teacher(Person):
def __init__(self, name, age, salary):
super().__init__(name, age)
self.salary = salary
def info(self):
print(self.name + ",", self.age, "years old, salary:", self.salary)
# create objects
kane = Person("Kane", 29)
kane.info()
kane = Teacher("Kane", 29, "5000000")
kane.info()
Kết quả
Kane, 29 years old.
Kane, 29 years old, salary: 5000000
Trong ví dụ trên, lớp Teacher kế thừa lớp Person. Lớp Teacher ghi đè hàm info()
kế thừa từ Person. Sau đó, chúng ta tạo ra các object của Person và Teacher. Các object này đều gọi một hàm có tên là info()
nhưng chúng cho kết quả thực thi khác nhau với từng loại đối tượng.