Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reescrita tópico sintaxe da herança #12

Merged
merged 11 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
301 changes: 277 additions & 24 deletions book/10-orientacao-objetos/03-heranca.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,277 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Para usar herança em Python, basta passar a superclasse entre parênteses na definição da subclasse. Veja o exemplo abaixo uma demonstração simples com a explicação na sequencia:"
"Para usar herança em Python, basta passar a superclasse entre parênteses na definição da subclasse. Veja o passo a passo de como construir uma estrutura simples com classes e subclasses."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1. Definindo a superclasse"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Primeiro, precisamos criar a superclasse que servirá como base para as subclasses. Vamos definir a classe `Animal`, que terá atributos e métodos comuns a todos os animais:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# Superclasse\n",
"class Animal:\n",
" def __init__(self, nome): # Método construtor da superclasse Animal\n",
" self.nome = nome"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Aqui, criamos um método construtor `__init__`, que recebe o nome do animal como parâmetro e o armazena em um atributo `self.nome`. Isso será comum a todos os animais.\n",
"\n",
"Agora, adicionamos alguns métodos genéricos que qualquer animal pode ter, como `comer` e `dormir`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Superclasse\n",
"class Animal:\n",
" def __init__(self, nome): # Método construtor da superclasse Animal\n",
" self.nome = nome\n",
"\n",
" def comer(self):\n",
" print(f\"{self.nome} está comendo.\")\n",
"\n",
" def dormir(self):\n",
" print(f\"{self.nome} está dormindo.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 2. Criando uma subclasse"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Agora que temos nossa superclasse `Animal`, vamos criar uma subclasse `Cachorro`, que herda de `Animal`. Na definição da classe `Cachorro`, passamos `Animal` entre parênteses. Isso indica que `Cachorro` é uma subclasse de `Animal`. Ou seja, `Cachorro` herda atributos e métodos de `Animal` sem precisar reescrevê-los."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Superclasse\n",
"class Animal:\n",
" def __init__(self, nome): # Método construtor da superclasse Animal\n",
" self.nome = nome\n",
"\n",
" def comer(self):\n",
" print(f\"{self.nome} está comendo.\")\n",
"\n",
" def dormir(self):\n",
" print(f\"{self.nome} está dormindo.\")\n",
"\n",
"# Subclasse \n",
"class Cachorro(Animal):\n",
" pass"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Aqui, estamos dizendo que `Cachorro` herda de `Animal`, mas ainda não adicionamos nada específico à subclasse. Vamos expandir essa subclasse."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3. Definindo o construtor da subclasse"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Aqui talvez seja o ponto principal. Na subclasse `Cachorro`, estamos executando o construtor da superclasse `Animal` com a linha `super().__init__(nome)`. Isso é necessário para que a subclasse tenha acesso aos atributos e métodos da superclasse. Percebam que o método construtor `__init__` da superclasse recebe apenas `nome` como parâmetro.\n",
"\n",
"A subclasse Cachorro precisa ter alguns atributos próprios, como a `raça`. Para isso fazemos uma atribuindo o parâmetro `nome` ao self."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"# Superclasse\n",
"class Animal:\n",
" def __init__(self, nome): # Método construtor da superclasse Animal\n",
" self.nome = nome\n",
"\n",
" def comer(self):\n",
" print(f\"{self.nome} está comendo.\")\n",
"\n",
" def dormir(self):\n",
" print(f\"{self.nome} está dormindo.\")\n",
"\n",
"# Subclasse \n",
"class Cachorro(Animal):\n",
" def __init__(self, nome: str, raca: str):\n",
" super().__init__(nome) # Chamando o construtor da superclasse Animal\n",
" self.raca = raca # Novo atributo exclusivo da subclasse Cachorro"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4. Adicionando métodos específicos a subclasse"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Agora podemos definir um método que apenas a classe `Cachorro` possui, como `latir`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Superclasse\n",
"class Animal:\n",
" def __init__(self, nome): # Método construtor da superclasse Animal\n",
" self.nome = nome\n",
"\n",
" def comer(self):\n",
" print(f\"{self.nome} está comendo.\")\n",
"\n",
" def dormir(self):\n",
" print(f\"{self.nome} está dormindo.\")\n",
"\n",
"# Subclasse \n",
"class Cachorro(Animal):\n",
" def __init__(self, nome: str, raca: str):\n",
" super().__init__(nome) # Chamando o construtor da superclasse Animal\n",
" self.raca = raca # Novo atributo exclusivo da subclasse Cachorro\n",
" \n",
" def latir(self):\n",
" print(f\"{self.nome}, o {self.raca}, está latindo!\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 5. Reutilizando métodos da superclasse"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Com a subclasse `Cachorro` pronta, podemos agora criar uma instância dela e testá-la:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"cachorro = Cachorro(\"Rex\", \"Labrador\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Aqui, criamos um objeto `cachorro` do tipo `Cachorro`, passando o nome \"Rex\" e a raça \"Labrador\".\n",
"\n",
"Graças à herança, podemos utilizar os métodos comer e dormir definidos na superclasse Animal (`comer` e `dormir`), mesmo que eles não existam diretamente na subclasse Cachorro. Estamos reutilizando o método da superclasse `Animal`."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Rex está comendo.\n",
"Rex está dormindo.\n"
]
}
],
"source": [
"# Superclasse\n",
"class Animal:\n",
" def __init__(self, nome): # Método construtor da superclasse Animal\n",
" self.nome = nome\n",
"\n",
" def comer(self):\n",
" print(f\"{self.nome} está comendo.\")\n",
"\n",
" def dormir(self):\n",
" print(f\"{self.nome} está dormindo.\")\n",
"\n",
"# Subclasse \n",
"class Cachorro(Animal):\n",
" def __init__(self, nome: str, raca: str):\n",
" super().__init__(nome) # Chamando o construtor da superclasse Animal\n",
" self.raca = raca # Novo atributo exclusivo da subclasse Cachorro\n",
" \n",
" def latir(self):\n",
" print(f\"{self.nome}, o {self.raca}, está latindo!\")\n",
"\n",
"cachorro = Cachorro(\"Rex\", \"Labrador\") # Criando instância da subclasse Cachorro\n",
"\n",
"cachorro.comer() # Reutilizando métodos da superclasse Animal\n",
"cachorro.dormir() # Reutilizando métodos da superclasse Animal"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 6. Usando métodos da subclasse"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"E finalmente chamamos o método `latir`, que é exclusivo da subclasse `Cachorro`:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
Expand All @@ -84,7 +348,7 @@
"source": [
"# Superclasse\n",
"class Animal:\n",
" def __init__(self, nome): # 2.1\n",
" def __init__(self, nome): # Método construtor da superclasse Animal\n",
" self.nome = nome\n",
"\n",
" def comer(self):\n",
Expand All @@ -93,37 +357,26 @@
" def dormir(self):\n",
" print(f\"{self.nome} está dormindo.\")\n",
"\n",
"\n",
"# Subclasse\n",
"class Cachorro(Animal): # 1\n",
"# Subclasse \n",
"class Cachorro(Animal):\n",
" def __init__(self, nome: str, raca: str):\n",
" super().__init__(nome) # 2\n",
" self.raca = raca # 3\n",
"\n",
" def latir(self): # 4\n",
" super().__init__(nome) # Chamando o construtor da superclasse Animal\n",
" self.raca = raca # Novo atributo exclusivo da subclasse Cachorro\n",
" \n",
" def latir(self):\n",
" print(f\"{self.nome}, o {self.raca}, está latindo!\")\n",
"\n",
"cachorro = Cachorro(\"Rex\", \"Labrador\") # Criando instância da subclasse Cachorro\n",
"\n",
"cachorro = Cachorro(\"Rex\", \"Labrador\") # 5\n",
"\n",
"cachorro.comer() # 6\n",
"cachorro.dormir() # 6\n",
"cachorro.latir() # 7"
"cachorro.comer() # Reutilizando métodos da superclasse Animal\n",
"cachorro.dormir() # Reutilizando métodos da superclasse Animal\n",
"cachorro.latir() # Usando método exclusivo da subclasse Cachorro"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Temos algumas novidades no código acima, vamos entender melhor. Acompanhe pelas marcações numéricas no código:\n",
"\n",
"1. Na definição da classe `Cachorro`, passamos `Animal` entre parênteses. Isso indica que `Cachorro` é uma subclasse de `Animal`. Ou seja, `Cachorro` herda atributos e métodos de `Animal` sem precisar reescrevê-los.\n",
"2. Aqui talvez seja o ponto principal. Na subclasse `Cachorro`, estamos executando o construtor da superclasse `Animal` com a linha `super().__init__(nome)`. Isso é necessário para que a subclasse tenha acesso aos atributos e métodos da superclasse. Percebam que o método construtor `__init__` da superclasse (2.1) recebe apenas `nome` como parâmetro. \n",
"3. A subclasse `Cachorro` possui um atributo a mais que a superclasse `Animal`: `raca`.\n",
"4. Definição de um método `latir` que só a subclasse possui.\n",
"5. Criamos uma instância `cachorro` a partir da subclasse `Cachorro`\n",
"6. A maravilha da herança acontecendo: percebam que o método `.comer()` e `.dormir()` não foi definido na subclasse `Cachorro`, mas mesmo assim conseguimos chamá-lo! Estamos reutilizando o método da superclasse `Animal`.\n",
"7. E finalmente chamamos o método `.latir()` que só a subclasse possui.\n",
"\n",
"Agora, e se quisermos adicionar outras subclasses de `Animal`, como `Gato`, `Peixe`, ou outros animais? Basta criar novas subclasses de `Animal` e seguir a mesma lógica que fizemos com `Cachorro`."
]
Expand Down Expand Up @@ -346,7 +599,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.6"
"version": "3.12.7"
}
},
"nbformat": 4,
Expand Down
10 changes: 5 additions & 5 deletions book/10-orientacao-objetos/04-encapsulamento.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -347,10 +347,10 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 4,
"metadata": {
"tags": [
"raise-exception"
"tags":[
"raise-exception"
]
},
"outputs": [
Expand All @@ -368,7 +368,7 @@
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[1;32mIn[3], line 29\u001b[0m\n\u001b[0;32m 26\u001b[0m \u001b[38;5;28mprint\u001b[39m(conta\u001b[38;5;241m.\u001b[39msaldo)\n\u001b[0;32m 28\u001b[0m \u001b[38;5;66;03m# Mas por ser uma propriedade, não podemos modificar seu valor diretamente\u001b[39;00m\n\u001b[1;32m---> 29\u001b[0m \u001b[43mconta\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msaldo\u001b[49m \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m5000\u001b[39m\n",
"Cell \u001b[1;32mIn[4], line 29\u001b[0m\n\u001b[0;32m 26\u001b[0m \u001b[38;5;28mprint\u001b[39m(conta\u001b[38;5;241m.\u001b[39msaldo)\n\u001b[0;32m 28\u001b[0m \u001b[38;5;66;03m# Mas por ser uma propriedade, não podemos modificar seu valor diretamente\u001b[39;00m\n\u001b[1;32m---> 29\u001b[0m \u001b[43mconta\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msaldo\u001b[49m \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m5000\u001b[39m\n",
"\u001b[1;31mAttributeError\u001b[0m: property 'saldo' of 'ContaBancaria' object has no setter"
]
}
Expand Down Expand Up @@ -637,7 +637,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.6"
"version": "3.12.7"
}
},
"nbformat": 4,
Expand Down
Loading
Loading