# Herança é interfaces

A herança e as interfaces são conceitos fundamentais na programação de smart contracts em Solidity, permitindo a organização modular e reutilizável do código, a abstração de funcionalidades e a criação de contratos compatíveis. Vamos guiá-lo através dos conceitos básicos e da implementação prática de herança e interfaces em Solidity.

## Orientação a Objetos em Solidity

**Conceito Básico de OO**:

* **Objetos**: Pense nos objetos como entidades do mundo real. Por exemplo, um carro. Cada carro tem atributos (como cor, modelo, marca) e comportamentos (como acelerar, frear).
* **Classes**: Uma classe é como uma planta baixa (blueprint) para criar objetos. No caso dos carros, a classe definiria o que todo carro deve ter (atributos) e o que pode fazer (métodos).

**Definindo uma Classe (Contrato) em Solidity**:

* Em Solidity, um contrato pode ser visto como uma classe. Ele define um conjunto de dados (estado) e funções (comportamentos).

```solidity
pragma solidity ^0.8.0;

contract Car {
    // Atributos (estado)
    string public color;
    string public model;
    uint public mileage;

    // Construtor - inicializa o objeto
    constructor(string memory _color, string memory _model, uint _mileage) {
        color = _color;
        model = _model;
        mileage = _mileage;
    }

    // Método (função)
    function drive(uint distance) public {
        mileage += distance;
    }
}
```

**Instanciando Objetos**:

* Quando você cria um novo contrato Car, está criando uma instância dessa classe. Cada instância tem seu próprio estado.

```solidity
Car myCar = new Car("Red", "Tesla Model S", 100);
```

**Herança**:

* Assim como em outras linguagens orientadas a objetos, Solidity suporta herança, permitindo que um contrato herde as propriedades e métodos de outro contrato.

```solidity
contract ElectricCar is Car {
    uint public batteryLife;

    constructor(string memory _color, string memory _model, uint _mileage, uint _batteryLife)
    Car(_color, _model, _mileage) {
        batteryLife = _batteryLife;
    }

    function chargeBattery(uint amount) public {
        batteryLife += amount;
    }
}
```

**Encapsulamento**:

* Encapsulamento é a prática de esconder os detalhes internos e expor apenas o necessário. Em Solidity, podemos usar modificadores de visibilidade como `public`, `private`, e `internal` para controlar o acesso.

```solidity
contract Car {
    string public color;
    string private model;
    uint internal mileage;

    constructor(string memory _color, string memory _model, uint _mileage) {
        color = _color;
        model = _model;
        mileage = _mileage;
    }

    function drive(uint distance) public {
        mileage += distance;
    }

    function getModel() public view returns (string memory) {
        return model;
    }
}
```

**Desafio prático : Contas de Banco** Imagine um banco com diferentes tipos de contas: conta corrente, conta poupança e conta investimento. Cada conta possui características e funcionalidades próprias, como taxas de juros, limites de saque e opções de investimento.

* **Contas como contratos:** Cada tipo de conta pode ser visto como um contrato inteligente, com suas próprias regras e funções.
* **OO para organização:** A OO permite criar classes abstratas para as características básicas (conta) e classes derivadas para cada tipo de conta (corrente, poupança, investimento), com herança e redefinição de métodos.
* **Modularização:** Maior organização, reutilização de código, segurança e confiabilidade nas transações bancárias.

## Herança

Herança é um princípio da programação orientada a objetos que permite que um contrato (a classe base) transfira suas propriedades e métodos para outro contrato (a classe derivada). Isso promove a reutilização de código e facilita a manutenção.

**Exemplo de Herança:**

```solidity
// Contrato Pai: Veiculo
contract Veiculo {
    string marca;
    string modelo;

    constructor(string memory _marca, string memory _modelo) {
        marca = _marca;
        modelo = _modelo;
    }

    function getMarca() public view returns (string memory) {
        return marca;
    }

    function getModelo() public view returns (string memory) {
        return modelo;
    }
}

// Contrato Filho: Carro
contract Carro is Veiculo {
    uint256 numeroPortas;

    constructor(string memory _marca, string memory _modelo, uint256  _numeroPortas) Veiculo(_marca, _modelo) {
        numeroPortas = _numeroPortas;
    }

    function getNumeroPortas() public view returns (uint256) {
        return numeroPortas;
    }
}
```

Neste exemplo, o contrato `Carro` herda do contrato `Veiculo`. O contrato `Carro` possui as propriedades e métodos do `Veiculo`, como `marca`, `modelo`, `getMarca` e `getModelo`, além de adicionar sua própria propriedade `numeroPortas` e método `getNumeroPortas`.

**Herança Múltipla**

Solidity também suporta herança múltipla, permitindo que um contrato herde de vários contratos. Aqui está o código Solidity comentado, explicando o que cada parte faz:

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

// Definição do contrato A
contract A {
    
    // Declaração de uma variável de estado privada que armazena o endereço do dono do contrato
    address private dono;

    // Modificador de função que restringe a execução apenas ao dono do contrato
    modifier apenasDono() {
        require(msg.sender == dono, "Apenas o dono pode chamar essa funcao");
        _;
    }

    // Construtor do contrato que define o endereço do dono como o endereço que implanta o contrato
    constructor() {
        dono = msg.sender;
    }

    // Função pública que retorna uma string "Funcao A"
    function funcA() public pure returns (string memory) {
        return "Funcao A";
    }

    // Função pública restrita ao dono que retorna uma string "Funcao AX"
    function funcX() public apenasDono virtual view returns (string memory) {
        return "Funcao AX"; 
    }
}

// Definição do contrato B
contract B {

    // Função pública que retorna uma string "Funcao B"
    function funcB() public virtual pure returns (string memory) {
        return "Funcao B";
    }

    // Função pública que retorna uma string "Funcao BX"
    function funcX() public virtual view returns (string memory) {
        return "Funcao BX";
    }
}

// Definição do contrato C que herda de A e B
contract C is A, B {
    // Este contrato agora tem acesso a funcA e funcB

    // Sobrescrita da função funcX que é restrita ao dono, combinando a lógica dos contratos A e B
    function funcX() public apenasDono override(A, B) view returns (string memory) {
        // lógica adicional pode ser adicionada aqui
        return "Funcao CX";
    }

    // Sobrescrita da função funcB do contrato B
    function funcB() public override(B) pure returns (string memory) {
        return "Funcao CB";
    }
}
```

**Contrato A**

* `address private dono;`: Armazena o endereço do dono do contrato.
* `modifier apenasDono()`: Modificador que garante que apenas o dono pode executar a função.
* `constructor()`: Define o dono do contrato como o endereço que o implantou.
* `funcA()`: Função pública que retorna "Funcao A".
* `funcX()`: Função pública restrita ao dono que retorna "Funcao AX".

**Contrato B**

* `funcB()`: Função pública que retorna "Funcao B".
* `funcX()`: Função pública que retorna "Funcao BX".

**Contrato C**

* Herda de `A` e `B`.
* `funcX()`: Sobrescreve a função `funcX` dos contratos `A` e `B` e é restrita ao dono.
* `funcB()`: Sobrescreve a função `funcB` do contrato `B`.

**Benefícios da Herança:**

* **Reutilização de código:** Reduz a duplicação de código, promovendo a organização e a legibilidade do código.
* **Extensão de funcionalidades:** Permite a criação de contratos mais complexos e especializados, construindo sobre a base de contratos existentes.
* **Organização modular:** Facilita a estruturação do código em módulos distintos e interligados, promovendo a manutenção e a atualização do código.

## Interfaces

As interfaces em Solidity definem um conjunto de funções que um contrato deve implementar, sem fornecer a implementação das funções. As interfaces permitem a abstração de funcionalidades e a criação de contratos compatíveis.

**Exemplo de Interface:**

```solidity
// Interface: VeiculoInterface
interface VeiculoInterface {
    function getMarca() external view returns (string memory);
    function getModelo() external view returns (string memory);
}

// Contrato: Carro
contract Carro is VeiculoInterface {
    string marca;
    string modelo;

    constructor(string memory _marca, string memory _modelo) {
        marca = _marca;
        modelo = _modelo;
    }

    function getMarca() public view override returns (string memory) {
        return marca;
    }

    function getModelo() public view override returns (string memory) {
        return modelo;
    }
}
```

Neste exemplo, a interface `VeiculoInterface` define as funções `getMarca` e `getModelo`. O contrato `Carro` implementa a interface `VeiculoInterface`, garantindo que ele possui as funções definidas na interface.

**Benefícios das Interfaces:**

* **Abstração de funcionalidades:** Separa a definição da implementação, permitindo que diferentes contratos implementem as mesmas funções de maneira distinta.
* **Compatibilidade de contratos:** Facilita a interação entre contratos, garantindo que todos os contratos que implementam a mesma interface possuem as mesmas funções disponíveis.
* **Desacoplamento de contratos:** Reduz a dependência entre contratos, permitindo a fácil substituição de um contrato por outro que implementa a mesma interface.

## Usando Herança e Interfaces Juntas

A herança e as interfaces podem ser usadas juntas para criar uma estrutura modular e flexível para seus smart contracts. Você pode usar interfaces para definir funcionalidades abstratas que diferentes contratos podem implementar, e usar herança para criar contratos que herdam funcionalidades de outros contratos e implementam interfaces.

***Exemplo:***

```solidity
// Interface: VeiculoInterface
interface VeiculoInterface {
    function getMarca() external view returns (string memory);
    function getModelo() external view returns (string memory);
}

// Contrato Pai: Veiculo
contract Veiculo is VeiculoInterface {
    string marca;
    string modelo;

    constructor(string memory _marca, string memory _modelo) {
        marca

```

## Especificadores de Visibilidade em Herança e Interfaces em Solidity

Os especificadores de visibilidade em Solidity controlam o acesso a atributos e funções de um contrato, definindo quem pode acessá-los e de onde. No contexto de herança e interfaces, os especificadores de visibilidade assumem importância crucial na organização modular e no controle de acesso entre diferentes contratos.

Em Solidity, existem quatro especificadores de visibilidade principais: `external`, `public`, `internal` e `private`. Vamos explorar cada um deles com exemplos práticos.

**`public`**

* **Atributos:** Quando um atributo é declarado como `public`, Solidity automaticamente cria uma função getter para ele. Isso significa que o atributo pode ser acessado por qualquer pessoa dentro e fora do contrato.
* **Funções:** Funções `public` podem ser chamadas de dentro do contrato, por outros contratos e externamente através de transações.

***Exemplo***

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

contract PublicExample {
    uint public valorPublico;

    function setValorPublico(uint _valor) public {
        valorPublico = _valor;
    }
}
```

Neste exemplo, `valorPublico` pode ser lido externamente, e `setValorPublico` pode ser chamado tanto internamente quanto externamente.

***`external`***

* **Funções:** Funções `external` só podem ser chamadas de fora do contrato. Elas não podem ser chamadas internamente sem o uso da palavra-chave `this`.

***Exemplo***

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

contract ExternalExample {
    uint private valorExterno;

    function setValorExterno(uint _valor) external {
        valorExterno = _valor;
    }

    function chamarSetValorExterno(uint _valor) public {
        // Chamando uma função external de dentro do contrato
        this.setValorExterno(_valor);
    }
}
```

Neste exemplo, `setValorExterno` só pode ser chamada externamente ou internamente usando `this`.

**`internal`**

* **Atributos e Funções:** Atributos e funções `internal` podem ser acessados apenas dentro do contrato em que são definidos e em contratos que herdam desse contrato.

***Exemplo***

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

contract InternalExample {
    uint internal valorInterno;

    function setValorInterno(uint _valor) internal {
        valorInterno = _valor;
    }
}

contract DerivedInternalExample is InternalExample {
    function atualizarValorInterno(uint _valor) public {
        setValorInterno(_valor); // Chamando a função internal do contrato pai
    }
}
```

Neste exemplo, `valorInterno` e `setValorInterno` são acessíveis apenas dentro de `InternalExample` e `DerivedInternalExample`.

**`private`**

* **Atributos e Funções:** Atributos e funções `private` só podem ser acessados dentro do contrato em que são definidos. Eles não podem ser acessados por contratos derivados.

***Exemplo***

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

contract PrivateExample {
    uint private valorPrivado;

    function setValorPrivado(uint _valor) private {
        valorPrivado = _valor;
    }

    function atualizarValorPrivado(uint _valor) public {
        setValorPrivado(_valor); // Chamando a função private dentro do próprio contrato
    }
}

contract DerivedPrivateExample is PrivateExample {
    function tentarAcessarPrivado(uint _valor) public {
        // setValorPrivado(_valor); // Isto gerará um erro
    }
}
```

Neste exemplo, `valorPrivado` e `setValorPrivado` só podem ser acessados dentro de `PrivateExample`. Qualquer tentativa de acessá-los em `DerivedPrivateExample` resultará em um erro.

**Visibilidade em Herança:**

* **Atributos:** A visibilidade de um atributo herdado é preservada no contrato filho. Por exemplo, se um atributo for `private` no contrato pai, ele também será `private` no contrato filho.
* **Funções:** A visibilidade de uma função herdada pode ser modificada no contrato filho. Por exemplo, uma função `public` no contrato pai pode ser alterada para `private` no contrato filho.

**Visibilidade em Interfaces:**

* As interfaces definem apenas a assinatura das funções, não sua visibilidade.
* Ao implementar uma interface, o contrato deve escolher a visibilidade adequada para cada função, considerando a lógica do contrato e os princípios de encapsulamento.

***Exemplo de Visibilidade em Herança:***

```solidity
// Contrato Pai: Veiculo
contract Veiculo {
    string marca; // private
    string modelo; // public

    function getMarca() public view returns (string memory) {
        return marca;
    }

    function getModelo() public view returns (string memory) {
        return modelo;
    }
}

// Contrato Filho: Carro
contract Carro is Veiculo {
    uint256 numeroPortas;

    constructor(string memory _marca, string memory _modelo, uint256 _numeroPortas) Veiculo(_marca, _modelo) {
        numeroPortas = _numeroPortas;
    }

    function getNumeroPortas() public view returns (uint256) {
        return numeroPortas;
    }
}
```

Neste exemplo, o contrato `Veiculo` possui um atributo `marca` privado e um atributo `modelo` público. No contrato `Carro`, o atributo `marca` permanece privado, enquanto o atributo `modelo` pode ser acessado por contratos externos.

**Exemplo de Visibilidade em Interface:**

```solidity
// Interface: VeiculoInterface
interface VeiculoInterface {
    function getMarca() external view returns (string memory);
    function getModelo() external view returns (string memory);
}

// Contrato: Carro
contract Carro is VeiculoInterface {
    string marca;
    string modelo;

    constructor(string memory _marca, string memory _modelo) {
        marca = _marca;
        modelo = _modelo;
    }

    function getMarca() public view override returns (string memory) {
        return marca;
    }

    function getModelo() public view override returns (string memory) {
        return modelo;
    }
}
```

Neste exemplo, a interface `VeiculoInterface` define as funções `getMarca` e `getModelo`. O contrato `Carro` implementa a interface e escolhe a visibilidade `public` para ambas as funções.

**Considerações Importantes:**

* Utilize os especificadores de visibilidade com cuidado para garantir o encapsulamento e a segurança dos seus smart contracts.
* Evite expor atributos e funções desnecessariamente, limitando o acesso a apenas quem precisa deles.
* Avalie cuidadosamente a visibilidade de funções herdadas antes de modificá-las no contrato filho.
* Considere a utilização de interfaces para definir funcionalidades abstratas e permitir a implementação com diferentes visibilidades em diferentes contratos.

**Diferenças entre `internal` e `external`:**

* Acesso: `internal` é interno, enquanto `external` é externo.
* Chamadas: `internal` pode ser chamada internamente e por derivados, enquanto `external` só pode ser chamada externamente.
* Encapsulamento: `internal` promove encapsulamento, enquanto `external` expõe a interface da função.

Os especificadores de visibilidade são essenciais para controlar o acesso a atributos e funções em contratos inteligentes Solidity. Utilizar esses especificadores de maneira adequada ajuda a proteger dados sensíveis e a manter uma boa organização do código. Aqui está um resumo rápido:

* `public`: Acessível por qualquer pessoa dentro e fora do contrato.
* `external`: Acessível apenas de fora do contrato.
* `internal`: Acessível dentro do contrato e em contratos derivados.
* `private`: Acessível apenas dentro do contrato onde é definido.

## Herança de atributos , funções, construtor, modifier, events

A herança de contratos é uma técnica que permite a reutilização e extensão de código. Através da herança, contratos filhos podem herdar atributos (variáveis de estado), funções, construtores, modifiers e eventos dos contratos pais. Vamos detalhar como a herança funciona para cada um desses componentes:

### Atributos (Variáveis de Estado)

Quando um contrato herda de outro, ele automaticamente herda todas as variáveis de estado do contrato pai. Estas variáveis podem ser acessadas e modificadas diretamente no contrato filho, a menos que sejam declaradas como `private`.

**Exemplo:**

```solidity
pragma solidity ^0.8.0;

contract Parent {
    uint public value;
}

contract Child is Parent {
    function setValue(uint _value) public {
        value = _value;  // Acessa a variável de estado herdada
    }
}
```

### Funções

As funções de um contrato pai são herdadas pelo contrato filho e podem ser chamadas diretamente ou sobrescritas (override) no contrato filho. Para sobrescrever uma função, use a palavra-chave `override` no contrato filho e `virtual` no contrato pai.

**Exemplo:**

```solidity
pragma solidity ^0.8.0;

contract Parent {
    function sayHello() public virtual returns (string memory) {
        return "Hello from Parent";
    }
}

contract Child is Parent {
    function sayHello() public override returns (string memory) {
        return "Hello from Child";
    }
}
```

### Construtores

Construtores não são herdados diretamente, mas o contrato filho pode chamar o construtor do contrato pai utilizando a sintaxe de construtor de contrato pai. Isso é feito passando os argumentos necessários ao construtor do contrato pai na definição do construtor do contrato filho.

**Exemplo:**

```solidity
pragma solidity ^0.8.0;

contract Parent {
    uint public value;

    constructor(uint _value) {
        value = _value;
    }
}

contract Child is Parent {
    constructor(uint _value) Parent(_value) {
        // Pode adicionar lógica adicional aqui
    }
}
```

### Modifiers

Modifiers também são herdados pelos contratos filhos. Assim como funções, modifiers podem ser sobrescritos usando as palavras-chave `virtual` no contrato pai e `override` no contrato filho.

**Exemplo:**

```solidity
pragma solidity ^0.8.0;

contract Parent {
    modifier onlyOwner() virtual {
        require(msg.sender == owner, "Not the owner");
        _;
    }

    address public owner;

    constructor() {
        owner = msg.sender;
    }
}

contract Child is Parent {
    modifier onlyOwner() override {
        require(msg.sender == owner, "Not the owner");
        _;
    }

    function restrictedFunction() public onlyOwner {
        // Lógica da função restrita
    }
}
```

### Events

Eventos definidos em um contrato pai são herdados pelo contrato filho e podem ser emitidos tanto no contrato pai quanto no contrato filho.

**Exemplo:**

```solidity
pragma solidity ^0.8.0;

contract Parent {
    event ValueChanged(uint oldValue, uint newValue);

    uint public value;

    function setValue(uint _value) public {
        emit ValueChanged(value, _value);
        value = _value;
    }
}

contract Child is Parent {
    function updateValue(uint _value) public {
        emit ValueChanged(value, _value);  // Emitindo evento herdado
        value = _value;
    }
}
```

### Resumo

* **Atributos (Variáveis de Estado):** Herdados automaticamente, acessíveis a menos que `private`.
* **Funções:** Herdadas automaticamente, podem ser sobrescritas usando `virtual` e `override`.
* **Construtores:** Não são herdados diretamente, mas podem ser chamados no construtor do contrato filho.
* **Modifiers:** Herdados automaticamente, podem ser sobrescritos.
* **Events:** Herdados automaticamente, podem ser emitidos tanto pelo contrato pai quanto pelo contrato filho.

## Herança x struct x interface

A escolha entre structs, herança de contratos e interfaces depende do contexto específico e dos objetivos do seu contrato inteligente. Cada uma dessas ferramentas serve a diferentes propósitos. Aqui estão algumas diretrizes para ajudar a decidir quando usar structs, herança de contratos ou interfaces:

### Structs

**Quando usar structs:**

1. **Agrupamento de Dados:** Utilize structs para agrupar múltiplos tipos de dados relacionados em uma única unidade lógica. Isso é útil quando você tem várias propriedades que descrevem uma entidade (por exemplo, um usuário, uma transação, um produto).
2. **Organização de Dados Complexos:** Quando você precisa armazenar dados complexos no estado do contrato, structs ajudam a manter a organização e clareza.
3. **Simplificação de Funções:** Structs podem ser usadas como parâmetros ou valores de retorno de funções para simplificar a passagem e manipulação de dados.

**Exemplo de uso de struct:**

```solidity
pragma solidity ^0.8.0;

contract Marketplace {
    struct Product {
        uint id;
        string name;
        uint price;
        address seller;
    }

    mapping(uint => Product) public products;

    function addProduct(uint id, string memory name, uint price) public {
        products[id] = Product(id, name, price, msg.sender);
    }

    function getProduct(uint id) public view returns (Product memory) {
        return products[id];
    }
}
```

### Herança de Contratos

**Quando usar herança:**

1. **Reutilização de Código:** Utilize herança para reutilizar funcionalidades comuns entre diferentes contratos. Isso reduz a duplicação de código e facilita a manutenção.
2. **Modularidade:** Quando você tem funcionalidades que podem ser divididas em componentes menores e reutilizáveis. Contratos base podem fornecer funcionalidades comuns compartilhadas por contratos derivados.
3. **Extensão e Personalização:** Quando você precisa estender ou personalizar funcionalidades de um contrato existente sem modificar seu código original.
4. **Uso de Contratos Base:** Herança é útil para incorporar contratos base que fornecem funcionalidades padrão, como contratos de gerenciamento de propriedade (Ownable), pausabilidade (Pausable) ou controle de acesso (AccessControl).

**Exemplo de uso de herança:**

```solidity
pragma solidity ^0.8.0;

contract Ownable {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor() {
        _owner = msg.sender;
        emit OwnershipTransferred(address(0), _owner);
    }

    modifier onlyOwner() {
        require(_owner == msg.sender, "Ownable: caller is not the owner");
        _;
    }

    function transferOwnership(address newOwner) public onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

contract MyContract is Ownable {
    // MyContract herda as funcionalidades de Ownable
}
```

### Interfaces

**Quando usar interfaces:**

1. **Desacoplamento e Abstração:** Use interfaces para definir um conjunto de funções que devem ser implementadas por outros contratos, sem impor uma implementação específica. Isso promove a modularidade e permite que diferentes contratos interajam de maneira padronizada.
2. **Interoperabilidade:** Quando você precisa interagir com contratos externos (por exemplo, padrões como ERC20, ERC721), interfaces permitem chamar funções desses contratos sem precisar da implementação completa.
3. **Múltiplas Implementações:** Se você espera ter várias implementações diferentes para um conjunto de funções, usar interfaces define uma estrutura comum que todas as implementações devem seguir.

**Exemplo de uso de interface:**

```solidity
pragma solidity ^0.8.0;

interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);
    // Outras funções ERC20...
}

contract MyToken is IERC20 {
    mapping(address => uint256) private _balances;
    uint256 private _totalSupply;

    function totalSupply() external view override returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address account) external view override returns (uint256) {
        return _balances[account];
    }

    function transfer(address recipient, uint256 amount) external override returns (bool) {
        require(_balances[msg.sender] >= amount, "Insufficient balance");
        _balances[msg.sender] -= amount;
        _balances[recipient] += amount;
        return true;
    }

    // Implementação das outras funções ERC20...
}
```

***Considerações***

* **Structs** são ideais para agrupar e organizar dados relacionados em uma unidade lógica, facilitando o gerenciamento e a manipulação de dados complexos.
* **Herança** é útil para compartilhar lógica comum, modularizar funcionalidades e estender contratos existentes, promovendo reutilização e manutenção de código.
* **Interfaces** são essenciais para definir contratos padrão e garantir interoperabilidade entre diferentes contratos, promovendo uma arquitetura desacoplada e padronizada.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://valter-lobo.gitbook.io/fase-1-solidity-basico/material-encontro-7/heranca-e-interfaces.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
