1. Kế thừa (inheritance) trong Python
Tính kế thừa (inheritance) 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). Tính chất này đề cập đến việc định nghĩa một lớp mới (new class) dựa trên một lớp cũ đã có (existing class). Lớp mới được gọi là lớp dẫn xuất (derived class) hay lớp con (child class). Lớp cũ đã có gọi là lớp cơ sở (base class) hoặc lớp cha (parent class).
1.1. Lớp con và lớp cha trong Python
Python cũng là một ngôn ngữ lập trình hướng đối tượng nên cũng hỗ trợ tính kế thừa. Bất kỳ một lớp nào trong Python cũng có thể là một lớp cơ sở. Cú pháp kế thừa trong Python:
class BaseClass:
# Body of base class
class DerivedClass(BaseClass):
# Body of derived class
DerivedClass sẽ kế thừa các thuộc tính và phương thức từ BaseClass. Việc này chủ yếu là để tái sử dụng code. Hơn nữa, DerivedClass có thể định nghĩa thêm các thuộc tính và phương thức của chính nó.
Ví dụ tạo một lớp cha Person
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print(self.name + ",", self.age, "years old.")
# create objects of Person class
john = Person("John", 36)
john.info()
marry = Person("Marry", 35)
marry.info()
Ví dụ lớp con Student kế thừa lớp cha Person
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print(self.name + ",", self.age, "years old.")
# Student inherits from Person
# without add any other properties or methods
class Student(Person):
pass
# create an object of Student class
kane = Student("Kane", 29)
kane.info()
Kết quả
Kane, 29 years old.
Trong ví dụ trên, lớp Student kế thừa lớp Person mà không thêm bất cứ thuộc tính và phương thức nào cho riêng lớp Student. Tức là, lớp Student có cùng thuộc tính và phương thức như lớp Person.
Có những trường hợp lớp con không định nghĩa gì như lớp Student. Khi tạo một đối tượng của lớp Student thì Python sẽ gọi hàm __init__()
của lớp Person mà lớp Student kế thừa được.
1.2. Định nghĩa hàm __init__() trong lớp con
Chúng ta có thể định nghĩa lại hàm khởi tạo __init__()
trong lớp con. Lúc này, hàm __init__()
trong lớp con sẽ ghi đè (overriding) lên hàm __init__()
kế thừa được từ lớp cha.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print(self.name + ",", self.age, "years old.")
# Student inherits from Person
class Student(Person):
def __init__(self, name, age):
Person.__init__(name, age)
Trong ví dụ trên, chúng ta gọi lại hàm __init__()
của lớp cho Person trong lớp Student để đảm bảo tính kế thừa. Nếu không dùng Person.__init__(name, age)
thì chúng ta có thể dùng super().__init__(name, age)
.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print(self.name + ",", self.age, "years old.")
# Student inherits from Person
class Student(Person):
def __init__(self, name, age):
super().__init__(name, age)
Hàm super()
giúp lớp con tự động kế thừa các thuộc tính và phương thức từ lớp cha.
1.3. Lớp con có các thuộc tính và phương thức riêng
Lớp con thường có các thuộc tính và phương thức riêng của nó.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print(self.name + ",", self.age, "years old.")
# Student inherits from Person
class Student(Person):
def __init__(self, name, age, id):
super().__init__(name, age)
self.id = id
def infoStudent(self):
print(self.name + ",", self.age, "years old, id:", self.id)
son = Student("Son", 30, "0469191517")
son.infoStudent()
Kết quả
Son, 30 years old, id: 0469191517
Trong ví dụ trên, lớp Student kế thừa từ lớp Person. Và lớp Student có thêm thuộc tính id và phương thức infoStudent()
.
2. Method overriding trong Python
Lớp con có thể định nghĩa lại các phương thức được kế thừa từ lớp cha. Đó được gọi là method overriding.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print(self.name + ",", self.age, "years old.")
# Student inherits from Person
class Student(Person):
def __init__(self, name, age, id):
super().__init__(name, age)
self.id = id
def info(self):
print(self.name + ",", self.age, "years old, id:", self.id)
son = Student("Son", 30, "0469191517")
son.info()
Kết quả
Son, 30 years old, id: 0469191517
Trong ví dụ trên, lớp Student kế thừa phương thức info()
từ lớp Person. Và lớp Student đã định nghĩa lại phương thức info()
cho riêng nó.
3. Sử dụng hàm isinstance() và issubclass() trong Python
Hàm isinstance()
giúp kiểm tra một đối tượng có phải là một thực thể của một lớp hay không. Hàm issubclass()
giúp kiểm tra một lớp có phải là lớp con của một lớp khác hay không. Hàm type()
trả về kiểu dữ liệu của một biến trong Python.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print(self.name + ",", self.age, "years old.")
# Student inherits from Person
class Student(Person):
def __init__(self, name, age, id):
super().__init__(name, age)
self.id = id
def info(self):
print(self.name + ",", self.age, "years old, id:", self.id)
# check subclass
print("Is Student subclass of Person?", issubclass(Student, Person))
print("Is Person subclass of Student?", issubclass(Person, Student))
print("\n")
# create objects
kane = Person("Kane", 29)
print("Is kane an instance of Person?", isinstance(kane, Person))
print("Is kane an instance of Student?", isinstance(kane, Student))
son = Student("Son", 30, "0469191517")
print("Is son an instance of Person?", isinstance(son, Person))
print("Is son an instance of Student?", isinstance(son, Student))
print("\n")
# type of kane and son
print("Type of kane:", type(kane))
print("Type of son:", type(son))
Kết quả
Is Student subclass of Person? True
Is Person subclass of Student? False
Is kane an instance of Person? True
Is kane an instance of Student? False
Is son an instance of Person? True
Is son an instance of Student? True
Type of kane: <class '__main__.Person'>
Type of son: <class '__main__.Student'>
Chúng ta thấy lớp Student kế thừa từ lớp Person. Do đó, các đối tượng của lớp Student cũng là các đối tượng của Person. Còn các đối tượng của Person không phải là của Student.