À medida que os programas aumentam em tamanho e complexidade, gerir e organizar o código pode tornar-se bastante desafiante. Funções e variáveis podem estar espalhadas por diferentes partes de um programa, tornando difícil acompanhar o que está a acontecer e levando a um código desorganizado e difícil de manter. É aqui que entram as classes, um pilar da programação orientada a objetos.
💡
As classes são uma forma de agrupar dados e funções relacionados, criando o que chamamos de 'objetos'.
As classes são os conceitos fundamentais na programação orientada a objetos (POO).
As classes são como planos (ou "blueprints") para criar objetos no nosso código. Cada classe agrupa propriedades (dados) e métodos (funções) relacionados em unidades únicas. Por exemplo, num programa de jogo, pode ter classes como Player, Monster ou Item, cada uma contendo os seus próprios dados e métodos relevantes. Isto torna mais fácil compreender e gerir bases de código grandes, pois as funcionalidades relacionadas são agrupadas, tornando claro como interagem entre si.
Imagine que quer criar um software para modelar uma biblioteca. Pode ter livros na sua biblioteca, então precisará de criar uma classe Book:
class Book:
def __init__(self, title, author, pages):
self.title = title # Atribui o título à instância do livro
self.author = author # Atribui o autor à instância do livro
self.pages = pages # Atribui o número de páginas à instância do livro
A palavra-chave class introduz uma nova classe, seguida do seu nome (Book). A linha def __init__(self, title, author, pages): define o estado inicial da classe ou o construtor. É aqui que o objeto é inicializado. self refere-se à instância da classe. title, author e pages são atributos da classe.
Pode criar um novo objeto livro chamando a classe como se fosse uma função:
# Cria uma nova instância de Book
mockingbird = Book('To Kill a Mockingbird', 'Harper Lee', 281)
print(mockingbird.title) # To Kill a Mockingbird
print(mockingbird.author) # Harper Lee
print(mockingbird.pages) # 281
Repare que passamos To Kill a Mockingbird, Harper Lee e 281 como argumentos. Estes são passados para o método __init__ (quase como numa função regular).
Podemos criar várias instâncias da classe Book:
# criar mais instâncias de Book
book2 = Book('1984', 'George Orwell', 328)
book3 = Book('The Great Gatsby', author='F. Scott Fitzgerald', pages=180)
book4 = Book('Moby Dick', 'Herman Melville', pages=720)
# imprimir algumas informações sobre os livros
print(f'{book2.title} by {book2.author} has {book2.pages} pages.') # 1984 by George Orwell has 328 pages.
print(f'{book3.title} by {book3.author} has {book3.pages} pages.') # The Great Gatsby by F. Scott Fitzgerald has 180 pages.
print(f'{book4.title} by {book4.author} has {book4.pages} pages.') # Moby Dick by Herman Melville has 720 pages.
Tal como com as funções, podemos passar argumentos posicionais e nomeados para o método __init__.
Além dos dados, as classes também podem encapsular funcionalidades. Suponha que, no nosso sistema de biblioteca, queremos marcar um livro como lido. Podemos definir um método na nossa classe Book para este propósito:
class Book:
def __init__(self, title, author, pages):
self.title = title # Atribui o título à instância do livro
self.author = author # Atribui o autor à instância do livro
self.pages = pages # Atribui o número de páginas à instância do livro
self.is_read = False # O livro ainda não foi lido
def mark_as_read(self): # Um método da classe
self.is_read = True # Marca o livro como lido
mockingbird = Book('To Kill a Mockingbird', 'Harper Lee', 281)
print(mockingbird.is_read) # False, o livro ainda não foi lido
mockingbird.mark_as_read() # Marca o livro como lido
print(mockingbird.is_read) # True, o livro foi lido
O método mark_as_read altera o estado do atributo is_read para True. Podemos chamar este método em qualquer instância de Book. Isto demonstra como podemos agrupar dados e funcionalidades relacionadas utilizando classes em Python.
💡
Em Python, self é um nome convencional para o primeiro parâmetro em métodos de instância de uma classe. É uma referência à instância atual da classe. self é usado para aceder aos atributos e métodos da classe dentro da sua definição.
Quando cria um novo objeto da classe, o Python associa automaticamente o argumento self a esse novo objeto, por isso não precisa de passar self quando chama um método de instância.
Embora self não seja uma palavra reservada em Python, é amplamente utilizado devido ao estilo claro e legível que promove. É importante notar que poderia usar qualquer outro nome, mas usar self é fortemente recomendado pela comunidade e é considerado uma boa prática.
Desafio: Criar uma Classe Car
O seu desafio é criar uma classe Car que deve ter os seguintes atributos:
color (a cor do carro)
make (a marca do carro)
model (o modelo específico do carro)
year (o ano em que foi fabricado)
Estes atributos devem ser inicializados no método __init__ da classe.
Além disso, a classe Car deve ter um método display_details. Este método deve retornar uma representação em string dos detalhes do carro no formato [year] [color] [make] [model].
Input
Output
ㅤ
c = Car('red', 'Ferrari', 'F8', 2023); print(c.display_details())
2023 red Ferrari F8
ㅤ
c = Car('black', 'Tesla', 'Model S', 2021); print(c.display_details())