🇧🇷
Ethereum Developer Pack - PT
  • Ethereum Developer Pack - PT
  • Módulo 1
    • Introdução a Smart Contracts
      • Fundamentos de Blockchain
        • Histórico
        • Bitcoin
        • O que é Blockchain
        • Conceitos-chave em Blockchain
        • Como funciona a Blockchain
        • Tipos de Blockchain
        • Modelos de Consenso
      • A nova Internet
        • Web 3
        • Elementos Fundamentais
        • Impacto do Ethereum em Diversos Setores
      • Wallets
        • Componentes de uma wallet
        • Tipos de Wallet
        • Códigos Mnemônicos
      • Ethereum 101
        • Smart Contracts
        • Contas
          • Tipos de contas
          • Conteúdo das contas
        • Transações
          • Componentes
          • Ciclo de vida
        • Gás
        • Solidity
        • EVM
          • A máquina de estados
          • Opcodes
          • Como funciona a EVM
          • Clientes de execução
          • DApps
      • Blockchain Explorer
        • Funções de um blockchain explorer
        • Beneficios de utilizar um blockchain explorer
      • Remix
        • Características do Remix
        • Workspaces ou espaços de trabalho
        • Carregar e compilar um contrato
        • Implantar na máquina virtual do Remix (Remix VM)
        • Interagindo com funções
        • Deployar em uma rede pública
      • Crie seu primeiro Smart Contract
  • Módulo 2
    • Fundamentos de Solidity
      • Hello World
      • Tipos de Dados
      • Funções
      • Variáveis
        • Exercício 1
      • Operadores
        • Ejercicio 2
      • Constructor
        • Exercício 3
      • Convenções de nomenclatura
      • Tipos de armazenamento para variáveis
      • Estruturas de Controle
        • Exercício 4
      • Modificadores
      • Eventos
        • Exercício 5
      • Tipos de Referencia
        • Arrays
          • Exercício 6
        • Mappings
          • Exercício 7
        • Structs
          • Exercício 8
      • Address Payable
      • Como os contratos e funções recebem Ether.
      • Transferências de Ether
      • Conceitos Avançados
        • Codificação de ABI
        • Hashing
        • This
        • Herança
        • Abstract
        • Interface
        • Chamada entre contratos
        • EVM
        • ABI
        • Bytecode
        • Opcodes
  • Módulo 3
    • ERCs, Bibliotecas e Padrões de Desenvolvimento
      • Boas Práticas de Desenvolvimento
      • Padrões de Desenvolvimento
      • EIP & ERC
      • ERC-20
      • ERC-721
      • Open Zeppelin
      • Crie um Token ERC-20
      • Almacenamiento Descentralizado: IPFS
      • Crea un Token ERC-721
      • DeFi
  • Módulo 4
    • Kit de ferramentas para desenvolvimento na Ethereum
      • Requisitos para o módulo 4
        • Terminal
        • Git e Github
        • Node.js e npm
        • Visual Studio Code para Solidity
      • Toolkit
        • JSON-RPC
        • Ethers.js
          • Exercício
        • Hardhat
          • Implantação de um contrato no Hardhat
          • Implantação de um contrato em uma rede pública
        • Scaffold-ETH
          • Características do Scaffold-ETHCaracterísticas
          • Como instalar o Scaffold-ETH
  • Módulo 5
    • Segurança, Testes e Auditorias
      • Testes
        • Importância de realizar testes
        • Métodos para testar contratos inteligentes
          • Testes automatizados
          • Testes manuais
        • Conceitos importantes em testes
        • Ferramentas para testes
        • Testes com Hardhat
        • Recursos adicionais
      • Segurança
        • Uma mentalidade diferente de design
        • Principais vulnerabilidades em contratos inteligentes
          • Reentrancy attack (ataque de reentrada)
          • Replay attack (ataque de repetición)
          • Price Oracle Manipulation (Manipulación de Oráculos de Precios)
          • Missing Access Control (Pérdida de Control de Acceso)
          • Reward Manipulation (Manipulación de Recompensas)
          • Failure to Initialize (Falla al Inicializar)
          • Front-running
          • Invariant Breaks (Quebra de Invariantes)
          • Mishandling of ETH (Má gestão de ETH)
          • Denial of Service (DoS - Negação de Serviço)
          • Integer overflow and underflow (Overflow e Underflow de inteiros)
          • Phishing y Typosquatting
        • Recursos adicionais
      • Auditoria de smart contracts
        • Processo de Auditoria
        • Ferramentas
        • Como se preparar para uma auditoria
        • O teste Rekt
        • Desafios
        • Recursos adicionais
  • Contribuye
    • Kipu Explorer
Powered by GitBook
On this page
  1. Módulo 2
  2. Fundamentos de Solidity
  3. Conceitos Avançados

Herança

PreviousThisNextAbstract

Last updated 5 months ago

A herança é um princípio fundamental da programação orientada a objetos (OOP) que também está presente em Solidity. A herança permite que um contrato herde propriedades e comportamentos (variáveis de estado e funções) de um ou mais contratos "pais", promovendo assim a reutilização de código e a criação de relações hierárquicas entre contratos.

Características da Herança em Solidity

  • Reutilização de Código: A herança permite que contratos inteligentes reutilizem o código de outros contratos. Isso não apenas reduz a redundância, mas também promove a prática do princípio DRY (Don't Repeat Yourself - Não se Repita).

  • Hierarquia de Contratos: Solidity permite a criação de uma hierarquia de contratos, onde um contrato filho pode herdar de múltiplos contratos pais, seguindo um padrão de herança múltipla.

  • Sobrescrita de Funções: Os contratos filhos podem sobrescrever funções herdadas de seus contratos pais, permitindo personalizar ou estender a funcionalidade base. Para isso, utiliza-se o atributo override na função.

  • Modificadores de Visibilidade: Solidity utiliza modificadores de visibilidade (public, internal, private e external) para controlar o acesso às funções e variáveis de estado. As regras de visibilidade também se aplicam a contratos herdados.

Exemplo Básico de Herança

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// Contrato pai
contract Base {
    uint public data;

    constructor(uint _data) {
        data = _data;
    }

    function setData(uint _data) public {
        data = _data;
    }
}

// Contrato filho que herda Base
contract Derived is Base {
    constructor(uint _initialData) Base(_initialData) {
        // Inicializa o contrato pai com _initialData
    }

    // Sobscreve a função setData
    function setData(uint _data) public override {
        data = _data + 10; // Altere a implementação para somar 10 antes de armazenar.
    }
}

Neste exemplo, Derived herda de Base. Isso significa que Derived tem acesso à variável data e pode usar ou sobrescrever a função setData. Na função setData sobrescrita, modificamos a implementação para somar 10 ao _data antes de armazená-lo.

Herança multinivel

A herança multinível é um conceito onde um contrato herda de outro contrato, que por sua vez herda de outro, criando assim uma hierarquia de herança "multinível". Esse padrão permite a construção de relações hierárquicas complexas e a reutilização de código através de vários níveis de contratos.

Aqui está um exemplo de herança multinível em Solidity, que ilustra como um contrato pode herdar propriedades e comportamentos de vários contratos pai situados em diferentes níveis da hierarquia:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// Contrato de nivel base
contract Grandparent {
    uint public grandparentValue;

    constructor(uint _value) {
        grandparentValue = _value;
    }

    function setGrandparentValue(uint _value) public {
        grandparentValue = _value;
    }
}

// Primeiro nivel de herança
contract Parent is Grandparent {
    uint public parentValue;

    constructor(uint _grandparentValue, uint _parentValue) Grandparent(_grandparentValue) {
        parentValue = _parentValue;
    }

    function setParentValue(uint _value) public {
        parentValue = _value;
    }
}

// Segundo nivel de herança
contract Child is Parent {
    uint public childValue;

    constructor(uint _grandparentValue, uint _parentValue, uint _childValue) Parent(_grandparentValue, _parentValue) {
        childValue = _childValue;
    }

    function setChildValue(uint _value) public {
        childValue = _value;
    }
}

Explicação do código:

  • Grandparent: Este é o contrato de nível base que define uma variável grandparentValue e uma função setGrandparentValue para modificá-la. Ele também possui um construtor que inicializa grandparentValue.

  • Parent: Este contrato herda de Grandparent. Adiciona sua própria variável parentValue e uma função setParentValue para modificá-la. Seu construtor chama o construtor de Grandparent para inicializar grandparentValue, e também inicializa parentValue.

  • Child: Este é o contrato de nível mais baixo que herda de Parent (e, portanto, indiretamente de Grandparent). Ele adiciona uma variável childValue e uma função setChildValue. Seu construtor inicializa as variáveis de todos os níveis da hierarquia chamando o construtor de Parent, que por sua vez chama o construtor de Grandparent.

Este exemplo mostra como criar e utilizar relações hierárquicas em Solidity por meio da herança multinível, permitindo que os contratos filhos acessem e sobrescrevam propriedades e funções de seus ancestrais, promovendo a reutilização e modularidade do código.

Herança Hierárquica

A herança hierárquica em Solidity refere-se a um padrão onde múltiplos contratos filhos herdam de um único contrato pai, criando uma estrutura hierárquica em "forma de árvore" com um nó raiz comum. Esse padrão permite compartilhar lógica e propriedades comuns entre vários contratos derivados, mantendo ao mesmo tempo diferenças específicas em cada um deles.

Aquí te mostro un exemplo de herança hierárquica em Solidity:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// Contrato pai comum
contract Vehicle {
    string public brand;
    string public model;

    constructor(string memory _brand, string memory _model) {
        brand = _brand;
        model = _model;
    }

    function getVehicleInfo() public view returns (string memory, string memory) {
        return (brand, model);
    }
}

// Primeiro contrato filho que herda do Veículo
contract Car is Vehicle {
    uint public carMaxSpeed;

    constructor(string memory _brand, string memory _model, uint _maxSpeed)
        Vehicle(_brand, _model) {
        carMaxSpeed = _maxSpeed;
    }

    function getMaxSpeed() public view returns (uint) {
        return carMaxSpeed;
    }
}

// Segundo contrato filho que herda do Veículo
contract Truck is Vehicle {
    uint public truckLoadCapacity;

    constructor(string memory _brand, string memory _model, uint _loadCapacity)
        Vehicle(_brand, _model) {
        truckLoadCapacity = _loadCapacity;
    }

    function getLoadCapacity() public view returns (uint) {
        return truckLoadCapacity;
    }
}

Explicação do Código:

  • Vehicle: Este é o contrato base ou "pai" que define propriedades comuns (brand e model) e uma função (getVehicleInfo) aplicável a qualquer tipo de veículo. Ele funciona como o nó raiz comum na herança hierárquica.

  • Car e **Truck**: Esses são contratos "filhos" que herdam do contrato Vehicle. Cada um deles estende a funcionalidade base incluindo propriedades específicas (carMaxSpeed para Car e truckLoadCapacity para Truck) e funções adicionais para interagir com essas propriedades (getMaxSpeed e getLoadCapacity, respectivamente). Embora compartilhem algumas características comuns definidas em Vehicle, Car e Truck se especializam em diferentes aspectos dos veículos que representam.

Características da Herança Hierárquica:

  • Especialização: Permite que os contratos filhos se especializem adicionando ou modificando funcionalidades específicas.

  • Organização Clara: Facilita uma estrutura clara e lógica para os contratos, refletindo relações do mundo real e facilitando a compreensão e manutenção do código.

Esse padrão de herança é especialmente útil em situações onde diferentes entidades compartilham características comuns, mas também precisam de suas próprias implementações e características específicas.

Herança Múltipla

A herança múltipla permite que um contrato herde comportamentos e características de múltiplos contratos pais.

A herança múltipla pode ser muito poderosa, mas também pode introduzir complexidade e ambiguidades. É importante projetar cuidadosamente a arquitetura dos contratos para evitar problemas comuns, como colisão de nomes ou dependência circular entre contratos.

Exemplo:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract A {
    function foo() public pure returns(string memory) {
        return "A";
    }
}

contract B {
    function bar() public pure returns(string memory) {
        return "B";
    }
}

contract C is A, B {
    function fooBar() public pure returns(string memory) {
        return string(abi.encodePacked(foo(), bar()));
    }
}

Neste exemplo, o contrato C herda de ambos, A e B, e tem acesso às suas funções foo e bar, respectivamente. O contrato C introduz uma nova função fooBar que combina as saídas das funções herdadas.