Volver a la página principal
martes 10 diciembre 2024
2

Cómo usar herencia en Solidity para reutilizar código entre contratos

La herencia permite que un contrato (llamado contrato derivado) herede propiedades y funciones de otro contrato (llamado contrato base). Esto permite reutilizar el código sin necesidad de escribirlo de nuevo, además de facilitar la extensión de funcionalidades.

Características principales:

1. Reutilización de código: Evita duplicar lógica común entre contratos.

2. Modularidad: Permite construir contratos más organizados y mantenibles.

3. Polimorfismo: Los contratos derivados pueden sobrescribir funciones de los contratos base.

Declaración básica de herencia

Ejemplo básico

pragma solidity ^0.8.0;

// Contrato base
contract ContratoBase {
    string public mensaje = "Hola desde el contrato base";

    function saludar() public view returns (string memory) {
        return mensaje;
    }
}

// Contrato derivado
contract ContratoDerivado is ContratoBase {
    function cambiarMensaje(string memory nuevoMensaje) public {
        mensaje = nuevoMensaje;
    }
}

En este ejemplo:

  • ContratoDerivado hereda las propiedades y funciones de ContratoBase.
  • Puede acceder directamente a la variable mensaje y sobrescribirla en su propia lógica.

Sobrescritura de funciones

Un contrato derivado puede sobrescribir funciones definidas en un contrato base. Para hacerlo, se utiliza la palabra clave override.

Ejemplo de sobrescritura

contract Padre {
    function obtenerMensaje() public pure virtual returns (string memory) {
        return "Mensaje del contrato Padre";
    }
}

contract Hijo is Padre {
    function obtenerMensaje() public pure override returns (string memory) {
        return "Mensaje del contrato Hijo";
    }
}
  • La función obtenerMensaje en Padre se marca como virtual para permitir su sobrescritura.
  • La función en Hijo usa override para sobrescribirla.

Llamar a funciones del contrato base

El contrato derivado puede invocar funciones del contrato base mediante la palabra clave super.

Ejemplo de llamada al contrato base

contract Base {
    function saludar() public pure virtual returns (string memory) {
        return "Hola desde el contrato base";
    }
}

contract Derivado is Base {
    function saludar() public pure override returns (string memory) {
        return string(abi.encodePacked(super.saludar(), " y el contrato derivado"));
    }
}

En este ejemplo:

  • super.saludar() invoca la implementación de saludar en el contrato base.
  • La respuesta se concatena con un mensaje adicional en el contrato derivado.

Múltiples contratos base

Solidity permite heredar de múltiples contratos base, pero requiere resolver conflictos si estos contratos tienen funciones o variables con el mismo nombre.

Ejemplo de múltiples herencias

contract A {
    function mensaje() public pure virtual returns (string memory) {
        return "Mensaje desde A";
    }
}

contract B {
    function mensaje() public pure virtual returns (string memory) {
        return "Mensaje desde B";
    }
}

contract C is A, B {
    function mensaje() public pure override(A, B) returns (string memory) {
        return string(abi.encodePacked(A.mensaje(), " y ", B.mensaje()));
    }
}

En este caso:

  • C hereda de A y B.
  • La sobrescritura explícita resuelve el conflicto entre las implementaciones de mensaje.

Constructor en contratos heredados

Los contratos base pueden incluir constructores, que deben ser llamados explícitamente desde el contrato derivado.

Ejemplo con constructores

contract Base {
    uint public valor;

    constructor(uint _valor) {
        valor = _valor;
    }
}

contract Derivado is Base {
    constructor(uint _valor) Base(_valor) {
        // Lógica adicional del contrato derivado
    }
}
  • El constructor del contrato base Base recibe un argumento _valor.
  • Derivado invoca explícitamente el constructor del contrato base con Base(_valor).

Modificadores de acceso y herencia

Las funciones y variables heredadas respetan los modificadores de visibilidad definidos en el contrato base:

  • public: Accesible dentro y fuera del contrato derivado.
  • internal: Accesible dentro del contrato base y en los contratos derivados.
  • private: No accesible en contratos derivados.

Ejemplo

contract Base {
    string private privado = "Privado";
    string internal interno = "Interno";
    string public publico = "Publico";

    function obtenerInterno() public view returns (string memory) {
        return interno;
    }
}

contract Derivado is Base {
    function verInterno() public view returns (string memory) {
        return interno; // Permitido porque es `internal`.
    }

    // Esta función fallará si intentas acceder a `privado`.
}

Ventajas de la herencia en Solidity

1. Reutilización de código: Permite evitar duplicación y reduce el tamaño del contrato.

2. Organización: Promueve la modularidad y mejora la legibilidad.

3. Extensibilidad: Facilita agregar nuevas funcionalidades sin modificar contratos existentes.

Consideraciones importantes

1. Conflictos en múltiples herencias: Resuelve los conflictos explícitamente usando override.

2. Constructores explícitos: Llama a los constructores de los contratos base al implementar herencia.

3. Cuidado con private: Las propiedades privadas no se heredan, usa internal si deseas compartirlas con contratos derivados.

Referencias oficiales

Para más detalles sobre herencia en Solidity, consulta la documentación oficial de Solidity.

Etiquetas:
solidity
Compartir:
Creado por:
Author photo

Jorge García

Fullstack developer