Solidity - Anfangszuordnung der Struktur kann ignoriert werden

Ich habe herausgefunden, dass wir bei der Initialisierung von Strukturen den Zuordnungstyp einfach ignorieren können, zum Beispiel:

pragma solidity ^0.4.0;

contract C{
  struct Person{
    string name;
    mapping(address=>int) map;
    string[] nickNames;
    int age;
  }

  function init() constant returns (string, int){
    string[] memory nickNames = new string[](1);
    nickNames[0] = "cat1099";

    Person memory p = Person("Jack", nickNames, 23);

    return (p.name, p.age);
  }
}

In dem Office-Dokument , das ich nur in einem Code-Hinweis gefunden habe, heißt es: "Wir lassen den Zuordnungstyp aus.",Nachdem Sie diese Site durchsucht haben, hat hier jemand Folgendes gesagt:

Zuordnungen können als Hashtabellen betrachtet werden, die virtuell so initialisiert werden, dass jeder mögliche Schlüssel existiert und einem Wert zugeordnet wird, dessen Byte-Darstellung ausschließlich aus Nullen besteht: dem Standardwert eines Typs. Die Ähnlichkeit endet hier jedoch: Die Schlüsseldaten werden nicht wirklich in einem Mapping gespeichert, nur ihr keccak256-Hash wird verwendet, um den Wert nachzuschlagen.

Bedeutete das, Solidty kann keine Zuordnung in struct initialisieren, also ignoriere es einfach. Kann das jemand klarer machen, da es keine offizielle Erklärung dafür gibt?

Antworten (1)

Als Entwickler können Sie die Zuordnung als alle möglichen Schlüssel/Wert-Paare betrachten, wobei die Werte je nach Typ mit 0, falsch, leerem Array usw. initialisiert werden. Es muss nicht explizit initialisiert werden. Sie sind einfach.

Dies schließt Zuordnungen innerhalb von Strukturen ein. Die Werte bleiben null, bis sie explizit festgelegt werden.

Zuordnungen innerhalb von Strukturen können nützlich sein, ebenso wie Zuordnungen von Strukturen oder beides, wie unten beschrieben.

Schlüssel werden nicht in Mappings gespeichert.

In Betracht ziehenmapping(uint => address) numberedAddresses;

Der Schlüssel ( uint) wird gehasht, um einen "Slot" zu finden, und addressin diesem Slot gespeichert. Der Schlüssel selbst wird nicht gespeichert. Die einzige Möglichkeit, einen zugeordneten Wert abzurufen, besteht darin, ihn mit Kenntnis des Schlüssels zurückzurufen:

numberedAddress[key];

Es gibt einige Implikationen, mit denen Sie sich vertraut machen sollten. Es ist nicht möglich, die Schlüssel in einer Zuordnung aufzuzählen. Ebenso ist es nicht möglich, sie zu zählen. Wir könnten in allen Fällen sagen: "Alle möglichen Schlüssel existieren".

Wenn man die Schlüssel auflisten möchte, die wir tatsächlich setzen (gemeinsam), dann muss man die Schlüssel selbst woanders speichern. Es gibt hier einige Beispielmuster, zB Mapped Structs with Index, um zu verhindern, dass Dinge neu erfunden werden. Gibt es gut gelöste und einfache Speichermuster für Solidity? .

Das folgende Beispiel ist zum Herumspielen in Remix gedacht. Sie erhalten alle 0-Ergebnisse für jeden Schlüssel von den Gettern, bis Sie explizit etwas festlegen. Die letzten beiden Funktionen zeigen, wie man mit einer Zuordnung arbeitet, die in einer Struktur gespeichert ist.

Ich hoffe es hilft.

pragma solidity ^0.4.6;

contract Mappings {

    // For all new structs, all answer flags at all key locations are false until set. 

    struct UserStruct {
        uint balanceOf;
        bool isActive;
        mapping(uint => bool) answerFlags;
    }

    // Key => Struct. All keys initialize to 0.
    // Query any unset Key and get balanceOf == 0 and isActive == false.

    // (More common to use address => struct for "users") 

    mapping(uint => UserStruct) public userStructs;

    // Key => Bool. All keys initialize to false
    // Query any unset key and get false.

    mapping(uint => bool) public addressFlags;

    // Set values in storage

    function setUserStruct(uint key, uint balanceOf, bool isActive) public returns(bool success) {
        userStructs[key].balanceOf = balanceOf;
        userStructs[key].isActive  = isActive;
        return true;
    }

    function setAddressFlag(uint key, bool flagAddress) public returns(bool success) {
        addressFlags[key] = flagAddress;
        return true;
    }

    // Mapping inside a struct

    function getUserAnswerFlag(uint userStructKey, uint userAnswerKey) public constant returns(bool answerFlag) {
        return userStructs[userStructKey].answerFlags[userAnswerKey];
    }

    function setUserAnswerFlag(uint userStructKey, uint userAnswerKey, bool setValue) public returns(bool success) {
        userStructs[userStructKey].answerFlags[userAnswerKey] = setValue;
        return true;
    }

}