diff --git a/book/10-orientacao-objetos/03-heranca.ipynb b/book/10-orientacao-objetos/03-heranca.ipynb index 01e3c4e..355c1ed 100644 --- a/book/10-orientacao-objetos/03-heranca.ipynb +++ b/book/10-orientacao-objetos/03-heranca.ipynb @@ -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", @@ -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", @@ -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`." ] @@ -346,7 +599,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.6" + "version": "3.12.7" } }, "nbformat": 4, diff --git a/book/10-orientacao-objetos/04-encapsulamento.ipynb b/book/10-orientacao-objetos/04-encapsulamento.ipynb index 63d382f..6c95521 100644 --- a/book/10-orientacao-objetos/04-encapsulamento.ipynb +++ b/book/10-orientacao-objetos/04-encapsulamento.ipynb @@ -347,10 +347,10 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, "metadata": { - "tags": [ - "raise-exception" + "tags":[ + "raise-exception" ] }, "outputs": [ @@ -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" ] } @@ -637,7 +637,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.6" + "version": "3.12.7" } }, "nbformat": 4, diff --git a/book/10-orientacao-objetos/05-polimorfismo.ipynb b/book/10-orientacao-objetos/05-polimorfismo.ipynb index 5b4ab9b..7c29d50 100644 --- a/book/10-orientacao-objetos/05-polimorfismo.ipynb +++ b/book/10-orientacao-objetos/05-polimorfismo.ipynb @@ -280,9 +280,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pagamento de R$900.00 processado via pix.\n" + ] + } + ], "source": [ "forma_pagamento = \"pix\"\n", "\n", @@ -292,11 +300,11 @@ " taxa = valor_tota_compra * 0.02 # 2% de juros\n", " total = valor_tota_compra + taxa\n", "\n", - "elif forma_pagamentos == \"boleto\":\n", + "elif forma_pagamento == \"boleto\":\n", " desconto = valor_tota_compra * 0.05\n", " total = valor_tota_compra - desconto\n", "\n", - "elif forma_pagamentos == \"pix\":\n", + "elif forma_pagamento == \"pix\":\n", " desconto = valor_tota_compra * 0.10\n", " total = valor_tota_compra - desconto\n", "\n", @@ -341,7 +349,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.6" + "version": "3.12.7" } }, "nbformat": 4,