Ich versuche, eine grundlegende Vererbungshierarchie mit abstrakten/virtuellen Formalismen zu erstellen. Betrachten Sie die folgenden zwei Verträge:
Abstrakter Vertrag (IUser.sol):
contract IUser {
function addUser (address a) returns (bool) {}
}
Virtueller Vertrag (User.sol):
import "./IUser.sol";
contract User {
address[] userList;
function addUser (address a) returns (bool) {
userList.push(a);
}
Wenn ich versuche, beide Verträge bereitzustellen, zuerst die IUser.sol und dann die User.sol, mit Truffle, erhalte ich die Fehlermeldung "IUser ist nicht definiert". Irgendwelche Vorschläge? Außerdem, wie verwenden wir Schnittstellen in 0.4.11 und stellen sie mit Truffle Migration bereit?
Sie versuchen nicht, die abstrakte Schnittstelle bereitzustellen contract IUser
.
contract User is IUser {}
Sie implementieren (migrieren) User
. Andere Verträge können die Abstraktion verwenden, um die Schnittstelle zum Benutzer zu verstehen. User is IUser
schützt Sie vor bestimmten Arten von Entwicklerfehlern wie dem Versäumnis, eine Funktion in der Benutzeroberfläche zu definieren.
Ich hoffe es hilft.
Einige Klarstellungen, um auf die Kommentare unten zu antworten
Sie können keinen Vertrag mit einer abstrakten (undefinierten) Funktion bereitstellen. Es reagiert ähnlich auf einen Konstruktorfehler und wird nicht bereitgestellt.
Abstrakte (auch als Schnittstelle bezeichnete) Verträge, um den Overhead niedrig zu halten, wenn Verträge kommunizieren müssen. Es ist Geschmackssache, aber ich habe es für Implementierungen als nützlich empfunden, von Schnittstellen zu erben, um Fehler abzufangen.
Betrachten Sie ein Paar umfangreicher Verträge für ein Geschäft und einen Spediteur, die kommunizieren müssen. Beispielsweise muss der Laden den Versand arrangieren. Das wäre riesig:
import "./Shipping.sol";
contract Store {
Shipping s;
...
}
In der Tat, wenn man die Dinge auf diese Weise angeht, wird das Blockgaslimit während des Einsatzes ein Problem sein. Gute Nachrichten: Der Shop muss nicht die internen Abläufe des Versandvertrags kennen, sondern nur die Schnittstelle. So ...
contract ShippingInterface {
function shipStuff(bytes32 itemId, uint qty, bytes32 streetAddressId) public returns(bytes32 waybillId);
}
contract Store {
ShippingInterface s;
...
}
Im ersten Fall erbt Store den gesamten Bytecode für den Versand. Im zweiten Fall erbt es nur die kritischen ABI-Informationen, ist also viel kleiner. In beiden Fällen kann der Vertrag vom Konstruktor oder einer anderen Funktion instanziiert werden.
Das wird funktionieren:
function Store(address shippingContract) public {
Shipping s = Shipping(shippingContract);
}
aber so wird dies (zweiter Fall)
function Store(address shippingContract) public {
ShippingInterface s = ShippingInterface(shippingContract);
}
Der zweite Weg ist viel kompakter. Beachten Sie, dass in beiden Fällen ein tatsächlicher Versandvertrag bereitgestellt wird. Die Methoden unterscheiden sich nur darin, wie Store darüber informiert wird.
Aus Stilgründen kann es praktisch sein, wenn der Compiler Inkonsistenzen meldet, die sich während der Arbeit in den Code einschleichen. Dieser Stil funktioniert in vielen Fällen.
Versand.sol
contract ShippingInterface {
function doStuff() ... ;
}
contract Shipping is ShippingInterface {
function doStuff() .. { // define it }
}
Store.sol
import "./Shipping.sol";
contract Store {
ShippingInterface s;
...
}
Sie würden einen Versand und einen Shop bereitstellen. Sie würden niemals ein ShippingInterface bereitstellen – es ist nur eine Möglichkeit, die Schnittstelle zur Realität zu beschreiben. Und der Compiler wird sich beschweren, wenn etwas in der Schnittstelle beschrieben ist und es nicht in dem Vertrag definiert ist, den Sie bereitzustellen versuchen, was eine gute Sache ist.
Ich hoffe es hilft.
skarred14
Rob Hitchens
throw
. Versuchen Sie, es manuell bereitzustellen, und beheben Sie von dort aus, denke ich.skarred14
szerte
skarred14
szerte