Solidity 구문 (8) 기타
라이브러리(Libraries)
라이브러리는 계약과 유사하지만, 지정한 주소에 한 번만 배치하고, EVM의 특성인 DELEGATECALL (Homestead 이전에는 CALLCODE) 을 통해 코드를 복원하는 것이 목적이다.이것은 라이브러리 함수를 호출할 때, 그 코드는 호출 계약의 상하문에서 실행된다는 것을 의미한다.this를 사용하면 호출 계약을 가리키며 호출 계약의 저장소(storage)에 접근할 수 있습니다.하나의 계약은 하나의 독립된 코드 블록이기 때문에, 계약이 명확하게 제공한 상태 변수 (state variables) 를 호출하는 데만 접근할 수 있고, 그렇지 않으면 이 상태 변수를 알 수 있는 방법이 없다.
라이브러리 계약을 사용하는 계약은 라이브러리 계약을 은밀한 부모 계약(base contracts)으로 볼 수 있으며, 물론 상속 관계에 현저하게 나타나지 않는다.그러나 라이브러리 함수를 호출하는 방식은 매우 유사하다. 예를 들어 라이브러리 L에 함수 f()가 있으면 L.f()를 사용하면 접근할 수 있다.그 밖에 인터넷의 라이브러리 함수는 모든 계약에 대해 알 수 있다. 라이브러리를 하나의 부계약으로 상상하면 통할 수 있다.물론 내부 함수를 호출하는 것은 인터넷의 호출 관례를 사용하는데 이것은 모든 인터넷 유형이 들어갈 수 있음을 의미하고memory 유형은 복사하는 방식이 아니라 인용을 통해 전달된다는 것을 의미한다.EVM에서 이를 실현하기 위해 인터넷의 라이브러리 함수 코드와 그 중에서 호출된 모든 함수는 호출 계약에 끌어다 놓은 다음 DELEGATECALL 대신 일반적인 JUMP를 실행합니다.
다음의 예는 라이브러리를 어떻게 사용하는지 보여 준다. (다음에 using for 장에서 Set을 실현하기에 더욱 적합한 예가 있다.)pragma solidity ^0.4.0;
library Set {
// We define a new struct datatype that will be used to
// hold its data in the calling contract.
struct Data { mapping(uint => bool) flags; }
// Note that the first parameter is of type "storage
// reference" and thus only its storage address and not
// its contents is passed as part of the call. This is a
// special feature of library functions. It is idiomatic
// to call the first parameter 'self', if the function can
// be seen as a method of that object.
function insert(Data storage self, uint value)
returns (bool)
{
if (self.flags[value])
return false; // already there
self.flags[value] = true;
return true;
}
function remove(Data storage self, uint value)
returns (bool)
{
if (!self.flags[value])
return false; // not there
self.flags[value] = false;
return true;
}
function contains(Data storage self, uint value)
returns (bool)
{
return self.flags[value];
}
}
contract C {
Set.Data knownValues;
function register(uint value) {
// The library functions can be called without a
// specific instance of the library, since the
// "instance" will be the current contract.
if (!Set.insert(knownValues, value))
throw;
}
// In this contract, we can also directly access knownValues.flags, if we want.
}
위의 예는 다음과 같습니다.
pragma solidity ^0.4.0;
library Set {
// We define a new struct datatype that will be used to
// hold its data in the calling contract.
struct Data { mapping(uint => bool) flags; }
// Note that the first parameter is of type "storage
// reference" and thus only its storage address and not
// its contents is passed as part of the call. This is a
// special feature of library functions. It is idiomatic
// to call the first parameter 'self', if the function can
// be seen as a method of that object.
function insert(Data storage self, uint value)
returns (bool)
{
if (self.flags[value])
return false; // already there
self.flags[value] = true;
return true;
}
function remove(Data storage self, uint value)
returns (bool)
{
if (!self.flags[value])
return false; // not there
self.flags[value] = false;
return true;
}
function contains(Data storage self, uint value)
returns (bool)
{
return self.flags[value];
}
}
contract C {
Set.Data knownValues;
function register(uint value) {
// The library functions can be called without a
// specific instance of the library, since the
// "instance" will be the current contract.
if (!Set.insert(knownValues, value))
throw;
}
// In this contract, we can also directly access knownValues.flags, if we want.
}
Set을 호출합니다.contains,Set.remove,Set.insert는 deleGATECALL의 방식으로 external을 호출하는 계약과 라이브러리로 컴파일됩니다.만약 라이브러리를 사용한다면 주의해야 할 것은 실질적인 외부 함수 호출이 발생했다는 것이다.비록 msg.sender,msg.value,this는 이 호출의 값을 유지합니다. (Homestead 이전에는 CALLCODE, msg.sender, msg.value를 실제로 사용했기 때문에 변경됩니다.)
일반 계약에 비해 라이브러리의 제한:
이런 제한들은 장래에도 해제될 수 있다!
라이브러리 부착(Using for)
명령 using A for B;라이브러리에 정의된 함수 (라이브러리 A) 부터 임의의 종류 B 까지 부착할 수 있습니다.이 함수들은 호출 함수 대상의 실례를 기본적으로 첫 번째 인자로 받아들일 것입니다.문법은python의self 변수와 유사합니다.
using A for *의 효과는 라이브러리 A의 함수가 임의의 유형에 부착되는 것입니다.
이 두 가지 상황 중, 모든 함수는 첫 번째 매개 변수의 유형이 호출 함수의 대상 유형과 일치하지 않아도 부착된다.형식 검사는 함수가 실제로 호출될 때 함수 재부팅 검사도 실행됩니다.
using A for B;지령은 현재의 역할역에서만 유효하고 일시적으로 현재의 계약이라는 역할역만 지원하며 후속에도 이 제한을 해제하고 전체 범위에 적용할 수 있다.전역 범위에 영향을 미칠 수 있다면 일부 모듈(module)을 도입함으로써 데이터 형식은 라이브러리 함수를 통해 기능을 확장할 수 있고 모든 곳에서 비슷한 코드를 한 번씩 쓸 필요가 없다.
다음은 set의 예를 다시 쓰는 방식을 바꾸겠습니다.
pragma solidity ^0.4.0;
// This is the same code as before, just without comments
library Set {
struct Data { mapping(uint => bool) flags; }
function insert(Data storage self, uint value)
returns (bool)
{
if (self.flags[value])
return false; // already there
self.flags[value] = true;
return true;
}
function remove(Data storage self, uint value)
returns (bool)
{
if (!self.flags[value])
return false; // not there
self.flags[value] = false;
return true;
}
function contains(Data storage self, uint value)
returns (bool)
{
return self.flags[value];
}
}
contract C {
using Set for Set.Data; // this is the crucial change
Set.Data knownValues;
function register(uint value) {
// Here, all variables of type Set.Data have
// corresponding member functions.
// The following function call is identical to
// Set.insert(knownValues, value)
if (!knownValues.insert(value))
throw;
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.