ETH Kipu
  • Ethereum Developer Pack
  • Módulo 1
    • Intro a Smart Contracts
      • Fundamentos de Blockchain
        • Antecedentes
        • Bitcoin
        • Qué es Blockchain
        • Conceptos Clave en Blockchain
        • Cómo funciona la Blockchain
        • Tipos de Blockchain
        • Modelos de Consenso
      • El nuevo Internet
        • Web 3
        • Elementos Fundamentales
        • Impacto de Ethereum en Diversos Sectores
      • Wallets
        • Componentes de una wallet
        • Tipos de Wallet
        • Códigos mnemónicos
      • Ethereum 101
        • Smart Contracts
        • Cuentas
          • Tipos de cuentas
          • Contenido de cuentas
        • Transacciones
          • Componentes
          • Ciclo de vida
        • Gas
        • Solidity
        • EVM
          • La máquina de estados
          • Opcodes
          • Cómo funciona la EVM
          • Clientes de ejecución
          • DApps
      • Blockchain Explorer
        • Funciones de un blockchain explorer
        • Beneficios de utilizar un blockchain explorer
      • Remix
        • Características de Remix
        • Workspaces o espacios de trabajo
        • Cargar y compilar un contrato
        • Desplegar en la máquina virtual de Remix (Remix VM)
        • Interactuando con funciones
        • Desplegar en una red pública
      • Crea tu primer Smart Contract
  • Módulo 2
    • Fundamentos de Solidity
      • Hello World
      • Tipos de Datos
      • Funciones
      • Variables
        • Ejercicio 1
      • Operadores
        • Ejercicio 2
      • Constructor
        • Ejercicio 3
      • Convenciones de nomenclatura
      • Tipos de almacenamiento para variables
      • Estructuras de Control
        • Ejercicio 4
      • Modificadores
      • Eventos
        • Ejercicio 5
      • Tipos de Referencia
        • Arrays
          • Ejercicio 6
        • Mappings
          • Ejercicio 7
        • Structs
          • Ejercicio 8
      • Address Payable
      • Cómo reciben Ether los contratos y funciones
      • Transferencias de Ether
      • Conceptos Avanzados
        • Codificación ABI
        • Hashing
        • This
        • Herencia
        • Abstract
        • Interface
        • Llamadas entre contratos
        • EVM
        • ABI
        • Bytecode
        • Opcodes
  • Módulo 3
    • Estándares, Librerías y Patrones
      • Buenas Prácticas de Diseño
      • Patrones de Diseño
      • EIP y ERC
      • ERC-20
      • ERC-721
      • Open Zeppelin
      • Crea un Token ERC-20
      • Almacenamiento Descentralizado: IPFS
      • Crea un Token ERC-721
      • DeFi
  • Módulo 4
    • Toolkit para desarrollo en Ethereum
      • Requisitos para el módulo 4
        • Terminal
        • Git y Github
        • Node.js y npm
        • Visual Studio Code para Solidity
      • Toolkit
        • JSON-RPC
        • Ethers.js
          • Ejercicio
        • Hardhat
          • Despliegue de un contrato en Hardhat
          • Despliegue de un contrato en una red pública
        • Scaffold-ETH
          • Características
          • Cómo instalar Scaffold-ETH
  • Módulo 5
    • Seguridad, Pruebas y Auditoría
      • Pruebas
        • Importancia de realizar pruebas
        • Métodos para probar contratos inteligentes
          • Pruebas automatizadas
          • Pruebas manuales
        • Conceptos importantes en testing
        • Herramientas para testing
        • Testing con Hardhat
        • Recursos adicionales
      • Seguridad
        • Una mentalidad distinta de diseño
        • Principales vulnerabilidades en smart contracts
          • 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 (Ruptura de invariantes)
          • Mishandling of ETH (Mal manejo de ETH)
          • Denial of Service (DoS - Denegación de Servicio)
          • Integer overflow and underflow (desbordamiento y subdesbordamiento de enteros)
          • Phishing y Typosquatting
        • Recursos adicionales
      • Auditoría de smart contracts
        • Proceso de Auditoría
        • Herramientas
        • Cómo prepararse para una auditoría
        • El test Rekt
        • Retos
        • Recursos adicionales
  • Contribuye
    • Kipu Explorer
Powered by GitBook
On this page

Was this helpful?

  1. Módulo 2
  2. Fundamentos de Solidity
  3. Conceptos Avanzados

Herencia

PreviousThisNextAbstract

Last updated 8 months ago

Was this helpful?

La herencia es un principio fundamental de la programación orientada a objetos (OOP) que también se encuentra en Solidity. La herencia permite que un contrato herede propiedades y comportamientos (variables de estado y funciones) de uno o más contratos "padres", promoviendo así la reutilización de código y la creación de relaciones jerárquicas entre contratos.

Características de la Herencia en Solidity

  • Reutilización de Código: La herencia permite que los contratos inteligentes reutilicen el código de otros contratos. Esto no solo reduce la redundancia sino que también fomenta la práctica del principio DRY (Don't Repeat Yourself).

  • Jerarquía de Contratos: Solidity permite la creación de una jerarquía de contratos, donde un contrato hijo puede heredar de múltiples contratos padres, siguiendo un patrón de herencia múltiple.

  • Sobrescritura de Funciones: Los contratos hijos pueden sobrescribir funciones heredadas de sus contratos padres, lo que permite personalizar o extender la funcionalidad base. Para esto se utilizará el atributo override en la función.

  • Modificadores de Visibilidad: Solidity usa modificadores de visibilidad (public, internal, private, y external) para controlar el acceso a las funciones y variables de estado. Las reglas de visibilidad también aplican a los contratos heredados.

Ejemplo Básico de Herencia

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

// Contrato padre
contract Base {
    uint public data;

    constructor(uint _data) {
        data = _data;
    }

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

// Contrato hijo que hereda de Base
contract Derived is Base {
    constructor(uint _initialData) Base(_initialData) {
        // Inicializa el contrato padre con _initialData
    }

    // Sobrescritura de la función setData
    function setData(uint _data) public override {
        data = _data + 10; // Cambia la implementación para sumar 10 antes de almacenar
    }
}

En este ejemplo, Derived hereda de Base. Esto significa que Derived tiene acceso a la variable data y puede usar o sobrescribir la función setData. En la función setData sobrescrita, modificamos la implementación para sumar 10 al _data antes de almacenarlo.

Herencia multinivel

La herencia multinivel es un concepto donde un contrato hereda de otro contrato, que a su vez hereda de otro, creando así una jerarquía de herencia "multinivel". Este patrón permite la construcción de relaciones jerárquicas complejas y la reutilización de código a través de varios niveles de contratos.

Aquí tienes un ejemplo de herencia multinivel en Solidity, que ilustra cómo un contrato puede heredar propiedades y comportamientos de varios contratos padres situados en diferentes niveles de la jerarquía:

// 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;
    }
}

// Primer nivel de herencia
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 herencia
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;
    }
}

Explicación del código:

  • Grandparent: Este es el contrato de nivel base que define una variable grandparentValue y una función setGrandparentValue para modificarla. También tiene un constructor que inicializa grandparentValue.

  • Parent: Este contrato hereda de Grandparent. Añade su propia variable parentValue y una función setParentValue para modificarla. Su constructor llama al constructor de Grandparent para inicializar grandparentValue, y también inicializa parentValue.

  • Child: Este es el contrato de nivel más bajo que hereda de Parent (y, por lo tanto, indirectamente de Grandparent). Añade una variable childValue y una función setChildValue. Su constructor inicializa las variables de todos los niveles de la jerarquía llamando al constructor de Parent, que a su vez llama al constructor de Grandparent.

Este ejemplo muestra cómo se pueden crear y utilizar relaciones jerárquicas en Solidity mediante la herencia multinivel, permitiendo a los contratos hijos acceder y sobrescribir propiedades y funciones de sus ancestros, promoviendo la reutilización y la modularidad del código.

Herencia jerárquica

La herencia jerárquica en Solidity se refiere a un patrón donde múltiples contratos hijos heredan de un único contrato padre, creando una estructura jerárquica en "forma de árbol" con un nodo raíz común. Este patrón permite compartir lógica común y propiedades entre varios contratos derivados, manteniendo al mismo tiempo diferencias específicas en cada uno de ellos.

Aquí te muestro un ejemplo de herencia jerárquica en Solidity:

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

// Contrato padre común
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);
    }
}

// Primer contrato hijo que hereda de Vehicle
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 hijo que hereda de Vehicle
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;
    }
}

Explicación del Código:

  • Vehicle: Este es el contrato base o "padre" que define propiedades comunes (brand y model) y una función (getVehicleInfo) aplicable a cualquier tipo de vehículo. Funciona como el nodo raíz común en la herencia jerárquica.

  • Car y Truck: Estos son contratos "hijos" que heredan del contrato Vehicle. Cada uno de ellos extiende la funcionalidad base incluyendo propiedades específicas (carMaxSpeed para Car y truckLoadCapacity para Truck) y funciones adicionales para interactuar con esas propiedades (getMaxSpeed y getLoadCapacity, respectivamente). Aunque comparten algunas características comunes definidas en Vehicle, Car y Truck se especializan en diferentes aspectos de los vehículos que representan.

Características de la Herencia Jerárquica:

  • Especialización: Permite que los contratos hijos se especialicen añadiendo o modificando funcionalidades específicas.

  • Organización Clara: Facilita una estructura clara y lógica para los contratos, reflejando relaciones del mundo real y facilitando la comprensión y el mantenimiento del código.

Este patrón de herencia es especialmente útil en situaciones donde diferentes entidades comparten características comunes pero también necesitan sus propias implementaciones y características específicas.

Herencia múltiple

La herencia múltiple permite que un contrato herede comportamientos y características de múltiples contratos padres.

La herencia múltiple puede ser muy poderosa pero también puede introducir complejidad y ambigüedades. Es importante diseñar cuidadosamente la arquitectura de los contratos para evitar problemas comunes como la colisión de nombres o la dependencia circular entre contratos.

Ejemplo:

// 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()));
    }
}

En este ejemplo, el contrato C hereda de ambos, A y B, y tiene acceso a sus funciones foo y bar, respectivamente. El contrato C introduce una nueva función fooBar que combina las salidas de las funciones heredadas.