En este tutorial vamos a explicar en qué consiste y cómo funciona la herencia de contratos en Solidity. Si ya sabes programar con otros lenguajes de programación orientados a objetos que soporten herencia, seguramente encuentres muchas similitudes.
Qué es la herencia
La herencia es un mecanismo que permite estructurar y reutilizar el código creado en un contrato en otro contrato. Al contrato que hereda ciertas propiedades o funciones de otro contrato se le conoce como hijo, mientras que al contrato del que hereda dichos elementos se le conoce como padre.
La herencia no solamente se limita a una simple relación, sino que un contrato que hereda de otro también puede ser a su vez padre de otro contrato.
Cómo se implementa la herencia
Cuando creas un contrato que extiende de otro, seguramente quieras heredar ciertas funcionalidades. Por ejemplo, vamos a definir un contrato al que llamaremos Padre
que contendrá la propiedad x
y la función ejemplo
. Además, en su constructor, definiremos un constructor que inicialice la variable x
con un valor:
pragma solidity ^0.8.17;
contract Padre
{
uint x;
constructor(uint valor)
{
x = valor;
}
function ejemplo() internal
{
// Código de la función
}
}
Ahora vamos a crear otro contrato al que llamaremos Hijo
en un nuevo archivo. Nuestra intención es que este contrato herede del contrato Padre
, por lo que debemos importar el contrato Padre
mediante la sentencia import
.
Para definir la relación de herencia debes usar la sentencia is
justo después de escribir el nombre del Smart Contract, en la definición del mismo. Seguidamente debes referenciar el contrato del que debe heredar, que en nuestro caso es el contrato Padre
:
pragma solidity ^0.8.17;
import "./Padre.sol";
contract Hijo is Padre
{
constructor(uint valor) Padre(valor)
{
// x
}
function ejemplo2() internal
{
// Código de la función
}
}
Tal y como ves, en nuestro ejemplo también hemos agregado un constructor. En dicho constructor hemos indicado un argumento de entrada y luego hemos referenciado al contrato Padre
, aceptando también dicho argumento. Lo que hemos hecho es indicar que queremos ejecutar el constructor de la clase Padre
antes que el constructor de la clase Hijo
. Por ello, el valor de x
en el constructor de la clase Hijo
será inicialmente el del valor que pasemos al constructor.
Tal y como ves, lo que hemos hecho con el constructor es algo muy similar a lo que solemos hacer con los modificadores de funciones.
Herencia múltiple de contratos
Un contrato nos solamente puede heredar de un único contracto, sino que puede heredar de más de un contrato. Vamos a crear un nuevo archivo con la clase Padre2
:
pragma solidity ^0.8.17;
contract Padre2
{
uint x;
constructor()
{
x = 4;
}
}
Ahora vamos a modificar el contrato Hijo
para que también herede de Padre2
.
pragma solidity ^0.8.17;
import "./Padre.sol";
import "./Padre2.sol";
contract Hijo is Padre, Padre2
{
constructor(uint valor) Padre(valor) Padre2()
{
// x
}
function ejemplo2() internal
{
// Código de la función
}
}
Tal y como puedes comprobar, hemos importado el contrado Padre2
y luego hemos usado al misma sentencia is
que teníamos para definir la relación de herencia, agregando el contrato tras una coma. Además, también ejecutaremos el constructor del contrato Padre2
.
Si quisieses que la clase Hijo
heredase de más contratos, bastaría con seguir el mismo procedimiento.
Esto ha sido todo.