Classes e Métodos Abstratos - Python
Em programação, as classes geralmente representam objetos do mundo real. No entanto, há casos em que precisamos trabalhar com entidades sem uma forma específica. Por exemplo, a entidade "animal": existem animais específicos, como gato e cachorro, mas "animal" em si é um conceito abstrato. O mesmo ocorre com "figura geométrica": temos retângulos, quadrados, círculos, triângulos, mas "figura geométrica" não representa uma forma concreta. Para descrever tais entidades, utilizamos classes abstratas.
Em Python, os recursos para criar classes abstratas estão no módulo especial abc
import abc
As principais ferramentas desse módulo são a classe ABC
@abstractmethod
ABC
@abstractmethod
Classes abstratas são definidas de maneira semelhante às classes comuns, exceto que elas herdam da classe ABC
abc
import abc
class Shape(abc.ABC):
pass
Geralmente, classes abstratas declaram funcionalidades que serão comuns às classes derivadas. Essas funcionalidades podem não ter implementação, devendo ser definidas nas classes herdeiras. Esse tipo de funcionalidade é representado por métodos abstratos. Por exemplo, a classe "figura geométrica" pode ter métodos para calcular perímetro e área, mas a fórmula para calcular a área varia para cada figura. Podemos definir o método de cálculo de área como abstrato, utilizando a anotação @abstractmethod
abc
import abc
class Shape(abc.ABC):
@abc.abstractmethod
def area(self): pass # área da figura
Aqui, o método area()
pass
É importante notar que não podemos instanciar uma classe abstrata com métodos abstratos diretamente, usando o seu construtor:
import abc
class Shape(abc.ABC):
@abc.abstractmethod
def area(self): pass
shape = Shape() # Erro - isso não é permitido
print(shape)
As classes derivadas devem implementar todos os métodos abstratos da classe abstrata. Por exemplo, vamos criar uma classe para representar um retângulo:
import abc
class Shape(abc.ABC):
@abc.abstractmethod
def area(self): pass
# classe retângulo
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
rect = Rectangle(30, 50)
print("Rectangle area:", rect.area()) # Rectangle area: 1500
Aqui, a classe Rectangle
area()
Da mesma forma, podemos definir outras figuras. Por exemplo, vamos adicionar uma classe para representar um círculo:
import abc
class Shape(abc.ABC):
@abc.abstractmethod
def area(self): pass
# classe retângulo
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
# classe círculo
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return self.radius * self.radius * 3.14
def print_area(shape):
print("Area:", shape.area())
rect = Rectangle(30, 50)
circle = Circle(30)
print_area(rect) # Area: 1500
print_area(circle) # Area: 2826.0
Neste exemplo, definimos uma função print_area
Atributos e Métodos Não Abstratos
Classes abstratas também podem definir construtores, atributos e métodos não abstratos, que podem ser utilizados pelas classes derivadas:
import abc
class Shape(abc.ABC):
def __init__(self, x, y):
self.x = x
self.y = y
@abc.abstractmethod
def area(self): pass # método abstrato
def print_point(self): # método não abstrato
print("X:", self.x, "\tY:", self.y)
# classe retângulo
class Rectangle(Shape):
def __init__(self, x, y, width, height):
super().__init__(x, y)
self.width = width
self.height = height
def area(self):
return self.width * self.height
rect = Rectangle(10, 20, 100, 100)
rect.print_point() # X: 10 Y: 20
Aqui, a classe abstrata Shape
print_point