5.4 Herencia de contratos

html

Punto del curso de Solidity: 5.4 Herencia de contratos

La herencia en Solidity permite que un contrato adquiera propiedades y métodos de otro contrato, permitiendo así el reuso de código. Esto facilita la gestión y el mantenimiento del código y promueve la modularidad. En este punto, abordaremos en detalle cómo funciona la herencia de contratos en Solidity, comprendiendo cómo se implementa y los diferentes matices que se presentan en su uso.

Conceptos Básicos

La herencia permite a un contrato (llamado hijo o derivado) heredar funciones y variables de otro contrato (llamado padre o base). La sintaxis básica para declarar tal relación es:

contract Base {
    // Código del contrato base
}

contract Derived is Base {
    // Código del contrato derivado
}

En este ejemplo sencillo, el contrato Derived hereda todo el comportamiento y estado del contrato Base. Vamos a profundizar más en los detalles, utilizando ejemplos más elaborados y comentarios explicativos.

Herencia Simple

Este primer ejemplo muestra cómo implementar la herencia simple:

// Contrato base
contract Animal {
    string public species

    constructor(string memory _species) {
        species = _species
    }

    function makeSound() public pure returns (string memory) {
        return Some generic sound
    }
}

// Contrato derivado
contract Dog is Animal {
    // Llamamos al constructor del contrato base
    constructor() Animal(Dog) {}

    // Sobrescribimos la función makeSound() en el contrato derivado
    function makeSound() public pure override returns (string memory) {
        return Bark
    }
}

En este ejemplo, el contrato Dog hereda de Animal. Observamos cómo se llama al constructor del contrato base desde el contrato derivado, pasando el valor Dog para la variable species. Además, sobrescribimos la función makeSound en el contrato derivado.

Herencia Múltiple

Solidity soporta herencia múltiple, lo que significa que un contrato puede heredar de múltiples contratos base. Esto puede ser útil pero también puede complicar el diseño. Evalúa cuidadosamente su uso.

// Contrato base 1
contract Base1 {
    function getNumber() public pure returns (uint) {
        return 1
    }
}

// Contrato base 2
contract Base2 {
    function getNumber() public pure returns (uint) {
        return 2
    }
}

// Contrato derivado que hereda de Base1 y Base2
contract Derived is Base1, Base2 {
    // Sobrescribimos la función getNumber() para resolver ambigüedad
    function getNumber() public pure override(Base1, Base2) returns (uint) {
        return super.getNumber() // Debe decidir cuál super usar
    }
}

En el contrato Derived, heredamos de Base1 y Base2. Dado que ambos contratos tienen una función getNumber, es necesario sobrescribir esta función en el contrato derivado y resolver cualquier ambigüedad.

Orden de Inicialización de Constructores

El orden de inicialización de los constructores sigue la cadena de herencias de arriba hacia abajo, es decir, los contratos base se inicializan antes que el propio contrato derivado.

// Contrato base A
contract A {
    constructor() {
        // Código de inicialización de A
    }
}

// Contrato base B
contract B {
    constructor() {
        // Código de inicialización de B
    }
}

// Contrato derivado C que hereda de A y B
contract C is A, B {
    constructor() A() B() {
        // Código de inicialización de C
    }
}

En este ejemplo, los constructores de los contratos A y B se ejecutan antes del constructor del contrato C. Es importante respetar este orden para evitar comportamientos inesperados.

Visibilidad y Herencia

La visibilidad de las funciones y variables (public, internal, private) también afecta cómo se comporta la herencia. Una función private no es accesible para contratos derivados, mientras que una función internal sí lo es.

contract Parent {
    uint private x // Sólo accesible en este contrato
    uint internal y // Accesible en este contrato y en contratos derivados
    uint public z // Accesible por cualquier contrato

    function privateFunc() private view returns (uint) {
        return x
    }

    function internalFunc() internal view returns (uint) {
        return y
    }

    function publicFunc() public view returns (uint) {
        return z
    }
}

contract Child is Parent {
    function test() public view returns (uint) {
        // uint a = privateFunc() // Error: no se puede acceder a funciones privadas
        uint b = internalFunc() // OK
        uint c = publicFunc() // OK
        return b   c
    }
}

En este código, el contrato Child puede acceder a funciones internal y public del contrato padre, pero no puede acceder a funciones private.

Resumen

  • La herencia en Solidity permite reutilizar código, lo cual facilita la modularidad y el mantenimiento.
  • Se puede implementar tanto herencia simple como múltiple, teniendo cuidado con la resolución de ambigüedades.
  • El orden de inicialización de constructores sigue la cadena de herencias de arriba hacia abajo.
  • La visibilidad de los métodos y variables afecta si estos pueden ser heredados y cómo.

La herencia es una herramienta poderosa en Solidity, pero debe ser utilizada con cuidado para mantener la claridad y la eficiencia del código.

AnteriorSiguiente

[mwai_chat]

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *