Khóa học python

Interfaces trong Python

0 phút đọc

Interfaces là một khái niệm quan trọng trong lập trình hướng đối tượng (OOP), cho phép định nghĩa các phương thức mà một lớp phải triển khai mà không cần cung cấp triển khai cụ thể. Mặc dù Python không có từ khóa interface như các ngôn ngữ khác (ví dụ: Java, C#), nhưng Python vẫn hỗ trợ khái niệm này thông qua các lớp trừu tượng (abstract classes) và module abc (Abstract Base Classes).

Lớp trừu tượng (Abstract Classes)

Lớp trừu tượng là một lớp không thể được khởi tạo trực tiếp và thường chứa một hoặc nhiều phương thức trừu tượng. Một phương thức trừu tượng là một phương thức được khai báo nhưng không có triển khai cụ thể. Các lớp con phải triển khai các phương thức trừu tượng này.

Sử dụng module abc

Module abc trong Python cung cấp các công cụ để định nghĩa các lớp trừu tượng và phương thức trừu tượng. Để định nghĩa một lớp trừu tượng, bạn cần kế thừa từ ABC (Abstract Base Class) và sử dụng decorator @abstractmethod để đánh dấu các phương thức trừu tượng.

Ví dụ:

from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

    @abstractmethod
    def perimeter(self):
        pass

Trong ví dụ trên, Shape là một lớp trừu tượng với hai phương thức trừu tượng areaperimeter. Các lớp con của Shape phải triển khai các phương thức này.

Triển khai Interfaces

Các lớp con kế thừa từ lớp trừu tượng phải triển khai tất cả các phương thức trừu tượng. Nếu không, chúng cũng sẽ trở thành các lớp trừu tượng và không thể được khởi tạo.

Ví dụ:

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

    def perimeter(self):
        return 2 * (self.width + self.height)

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return 3.14 * self.radius * self.radius

    def perimeter(self):
        return 2 * 3.14 * self.radius

Trong ví dụ trên, RectangleCircle là các lớp con của Shape và chúng đã triển khai các phương thức trừu tượng areaperimeter.

Sử dụng Interfaces

Bạn có thể sử dụng các lớp trừu tượng như các interfaces để đảm bảo rằng các lớp con tuân thủ một giao diện cụ thể.

Ví dụ:

shapes = [Rectangle(2, 3), Circle(5)]

for shape in shapes:
    print(f"Area: {shape.area()}")
    print(f"Perimeter: {shape.perimeter()}")

Kết quả:

Area: 6
Perimeter: 10
Area: 78.5
Perimeter: 31.400000000000002

Kiểm tra tính kế thừa

Bạn có thể sử dụng hàm isinstance() để kiểm tra xem một đối tượng có phải là thể hiện của một lớp cụ thể hoặc một lớp trừu tượng hay không.

Ví dụ:

rect = Rectangle(2, 3)
circle = Circle(5)

print(isinstance(rect, Shape))  # Kết quả: True
print(isinstance(circle, Shape))  # Kết quả: True
print(isinstance(rect, Rectangle))  # Kết quả: True
print(isinstance(circle, Rectangle))  # Kết quả: False

Đa kế thừa và Interfaces

Python hỗ trợ đa kế thừa, cho phép một lớp kế thừa từ nhiều lớp cơ sở. Điều này có thể hữu ích khi bạn muốn một lớp tuân thủ nhiều interfaces.

Ví dụ:

class Drawable(ABC):
    @abstractmethod
    def draw(self):
        pass

class Movable(ABC):
    @abstractmethod
    def move(self, x, y):
        pass

class GraphicObject(Drawable, Movable):
    def draw(self):
        print("Drawing object")

    def move(self, x, y):
        print(f"Moving object to ({x}, {y})")

obj = GraphicObject()
obj.draw()  # Kết quả: Drawing object
obj.move(10, 20)  # Kết quả: Moving object to (10, 20)

Trong ví dụ trên, GraphicObject kế thừa từ cả DrawableMovable, và phải triển khai các phương thức drawmove.

Interfaces và Duck Typing

Python là một ngôn ngữ lập trình động, và Duck Typing là một khái niệm quan trọng trong Python. Duck Typing cho phép bạn sử dụng các đối tượng mà không cần kiểm tra kiểu của chúng, miễn là chúng có các phương thức hoặc thuộc tính cần thiết.

Ví dụ:

class Duck:
    def quack(self):
        print("Quack!")

class Person:
    def quack(self):
        print("I can quack like a duck!")

def make_it_quack(duck):
    duck.quack()

duck = Duck()
person = Person()

make_it_quack(duck)  # Kết quả: Quack!
make_it_quack(person)  # Kết quả: I can quack like a duck!

Trong ví dụ trên, hàm make_it_quack không quan tâm đến kiểu của đối tượng mà nó nhận, miễn là đối tượng đó có phương thức quack.

Interfaces và Protocols (PEP 544)

Python 3.8 giới thiệu khái niệm Protocols thông qua PEP 544. Protocols cung cấp một cách để định nghĩa các interfaces mà không cần sử dụng các lớp trừu tượng. Protocols được định nghĩa bằng cách sử dụng module typing.

Ví dụ:

from typing import Protocol

class Quackable(Protocol):
    def quack(self) -> None:
        ...

class Duck:
    def quack(self):
        print("Quack!")

class Person:
    def quack(self):
        print("I can quack like a duck!")

def make_it_quack(duck: Quackable):
    duck.quack()

duck = Duck()
person = Person()

make_it_quack(duck)  # Kết quả: Quack!
make_it_quack(person)  # Kết quả: I can quack like a duck!

Trong ví dụ trên, Quackable là một Protocol định nghĩa phương thức quack. Hàm make_it_quack nhận một đối tượng tuân thủ giao diện Quackable.

Kết luận

Interfaces là một khái niệm quan trọng trong lập trình hướng đối tượng, giúp định nghĩa các phương thức mà một lớp phải triển khai mà không cần cung cấp triển khai cụ thể. Mặc dù Python không có từ khóa interface, nhưng Python vẫn hỗ trợ khái niệm này thông qua các lớp trừu tượng và Protocols. Bằng cách sử dụng các lớp trừu tượng và Protocols, bạn có thể đảm bảo rằng các lớp tuân thủ một giao diện cụ thể và viết mã nguồn linh hoạt, dễ bảo trì. Hy vọng rằng bài viết này đã cung cấp cho bạn một cái nhìn tổng quan và chi tiết về cách làm việc với interfaces trong Python.

Avatar
Được viết bởi

TechMely Team

Gợi ý câu hỏi phỏng vấn

Gợi ý bài viết

Bình luận

Chưa có bình luận nào

Khoá học javascript từ cơ bản đến chuyên sâuYoutube Techmely