Estoy tratando de crear una jerarquía de herencia básica con formalismos abstractos/virtuales. Considere los siguientes dos contratos:
Contrato abstracto (IUser.sol):
contract IUser {
function addUser (address a) returns (bool) {}
}
Contrato Virtual (Usuario.sol):
import "./IUser.sol";
contract User {
address[] userList;
function addUser (address a) returns (bool) {
userList.push(a);
}
Cuando trato de implementar ambos contratos, primero el IUser.sol y luego el User.sol, usando truffle, aparece el error "IUser no está definido". ¿Alguna sugerencia? Además, ¿cómo usamos las interfaces en 0.4.11 y las implementamos usando truffle migrate?
No intenta implementar la interfaz abstracta contract IUser
.
contract User is IUser {}
Usted implementa (migra) User
. Otros contratos pueden usar la abstracción para comprender la interfaz con el Usuario. User is IUser
lo protege de ciertos tipos de errores del desarrollador, como no poder definir una función en la interfaz.
Espero eso ayude.
Algunas aclaraciones para responder a los comentarios a continuación.
No puede implementar un contrato con una función abstracta (indefinida). Reaccionará de manera similar a una falla del constructor y no se implementará.
Contratos abstractos (también conocidos como interfaz) para mantener bajos los gastos generales cuando los contratos necesitan comunicarse. Es cuestión de gustos, pero me ha resultado útil que las implementaciones hereden de las interfaces como forma de detectar errores.
Considere un par de contratos grandes para una tienda y un transportista que necesitan comunicarse. Por ejemplo, la tienda necesita organizar el envío. Esto sería enorme:
import "./Shipping.sol";
contract Store {
Shipping s;
...
}
De hecho, si uno aborda las cosas de esta manera, el bloque gasLimit será un problema durante el despliegue. Buenas noticias: la tienda no necesita conocer el funcionamiento interno del contrato de envío, solo la interfaz. Entonces ...
contract ShippingInterface {
function shipStuff(bytes32 itemId, uint qty, bytes32 streetAddressId) public returns(bytes32 waybillId);
}
contract Store {
ShippingInterface s;
...
}
En el primer caso, Store hereda todo el bytecode para Shipping. En el segundo caso, hereda solo la información ABI crítica, por lo que es mucho más pequeño. En ambos casos, el contrato puede ser instanciado por el constructor o alguna otra función.
Esto funcionará:
function Store(address shippingContract) public {
Shipping s = Shipping(shippingContract);
}
pero también lo hará este (segundo caso)
function Store(address shippingContract) public {
ShippingInterface s = ShippingInterface(shippingContract);
}
La segunda forma es mucho más compacta. Tenga en cuenta que en ambos casos se implementa un contrato de envío real . Los métodos difieren solo en la forma en que se informa a Store al respecto.
Como cuestión de estilo, puede ser útil que el compilador informe sobre las incoherencias que se introducen en el código a medida que avanza. Este estilo funciona en muchos casos.
Envios.sol
contract ShippingInterface {
function doStuff() ... ;
}
contract Shipping is ShippingInterface {
function doStuff() .. { // define it }
}
Tienda.sol
import "./Shipping.sol";
contract Store {
ShippingInterface s;
...
}
Implementarías un envío y una tienda. Nunca implementaría una interfaz de envío: es solo una forma de describir la interfaz real. Y el compilador se quejará si hay algo descrito en la interfaz y no está definido en el contrato que está tratando de implementar, lo cual es bueno.
Espero eso ayude.
skarred14
Rob Hitchens
throw
. Intente implementarlo manualmente y solucione los problemas desde allí, supongo.skarred14
szerte
skarred14
szerte