생성자

(Constructor)

 

 

Solidity 언어는 객체지향언어(OOP)이기 때문에, 객체지향 특징 중 하나인 생성자(Constructor)를 가지고 있다. 만약, 객체의 초기화 코드가 필요하다면 이 생성자 안에 작성하면 된다.

 

Solidity 언어는 객체지향이긴하지만 블록체인의 스마트컨트랙트(Smart Contract)를 개발하기 위한 용도로 만들어졌기 때문에, 생성자가 가지는 특징 또한 다른 언어(ex, C++, Java)들과는 조금 다르니 주의하고 사용해야 한다.

 

Solidity 언어는 다른 객체지향언어와의 차이점은 프로그램 위에 객체를 무한정 만들 수 있는 것이 아닌, 블록체인에 계약서를 단 한번 만들고 이를 사용하는 것이라는 점이다.

 

 

생성자 특징

1. 생성자는 계약서가 배포될 때 호출된다.

2. 생성자가 필수는 아니지만, 사용한다면 단 1개 생성자만 작성해야한다.

3. 생성자를 직접 작성하지 않으면 기본생성자(default constructor)가 자동으로 생성된다.

4. 생성자의 가시성(visibility)는 internal이거나 public이어야 한다.

5. 생성자의 가시성을 internal으로 하면, 추상(abstract) 계약서라는 것이기 때문에, 단독으로는 사용을 할 수가 없다. 다른 계약서에서 상속을 받아서 사용해야 한다.

6. 생성자를 상속(inheritance)받는 방법은 두가지이다. 

 

 

생성자 특징 설명

1. 생성자는 계약서가 배포될 때 호출된다.

When a contract is created, its constructor (a function declared with the constructor keyword) is executed once. After the constructor has executed, the final code of the contract is deployed to the blockchain. This code includes all public and external functions and all functions that are reachable from there through function calls. The deployed code does not include the constructor code or internal functions only called from the constructor.

생성자는 계약서가 배포되는 때에 호출된다. 생성자가 실행된 후에 만들어진 계약서의 최종 코드(final code)가 블록체인에 배포되는데, 이 최종 코드에는 생성자 코드는 포함되지 않고, public과 external 함수들이 포함된다.

contract Coin {
   address public minter;
   constructor() public{
      minter = msg.sender;
   }
}

 

 

2. 생성자가 필수는 아니지만, 사용한다면 단 1개 생성자만 작성해야한다.

A constructor is optional. Only one constructor is allowed, which means overloading is not supported.

아래 코드는 계약서에 생성자가 2개이기 때문에 에러가 발생하는 코드이다. 문제를 해결하려면 아래 두개의 생성자 중에서 하나를 제거시키면 된다.

contract Joker {
   	uint x;
   	uint y;
	constructor(uint _x) public{ // 생성자 1
		x = _x;
   	}
   	constructor(uint _x, uint _y) public { // 생성자2
		x = _x;
		y = _y;
	}
}

 

 

3. 생성자를 직접 작성하지 않으면 기본생성자(default constructor)가 자동으로 포함된다.

If there is no constructor, the contract will assume the default constructor: constructor() public {}.

contract Joker {
	constructor() public{
	}
}

 

 

4. 생성자의 가시성(visibility)는 internal이거나 public이어야 한다.

Constructor functions can be either public or internal.

contract Joker {
	constructor() external{
   	} // error 발생

   	constructor() public{
   	} // 사용 가능

   	constructor() internal{
   	} // 사용 가능

	constructor() private{
   	} // error 발생
}

 

 

5. 생성자가 상속받을 때, internal을 사용하면 추상(abstract) 계약서라는 것으로 단독으로는 사용을 할 수가 없다. 다른 계약서로 상속을 받아서 사용해야 한다.

A constructor set as internal causes the contract to be marked as abstract.

아래 코드를 배포(Deploy)할 때, 계약A로 배포하면 계약을 생성할 수 없다는 메시지가 나오지만, 계약B로 배포하면 정상 생성된다.

pragma solidity ^0.4.22;
contract A {
   uint public a;
   constructor(uint _a) internal {
       a = _a;
   }
}

contract B is A(1) {
   constructor() public {}
}

 

 

6. 생성자를 상속(inheritance)받는 방법은 두가지이다.

One way is directly in the inheritance list (is Base(7)). The other is in the way a modifier would be invoked as part of the header of the derived constructor (Base(_y * _y)).

첫번째 방법은 상속받을 때 직접 argument를 넣어서 사용하는 방법이고, 두번째 방법은 modifier-style를 이용하는 방법이다. 내부적으로 기능적인 차이는 없으니 편의에 맞게 사용한다.

pragma solidity ^0.4.22;
contract Parent {
	uint x;
	constructor(uint _x) public { 
		x = _x; 
	}
	function getData() public returns(uint) { 
    	return x; 
    }
}

contract Child1 is Parent(7) { // 첫번째 방법
	constructor(uint _y) public {}
}

contract Child2 is Parent {
	constructor(uint _y) Parent(_y * _y) public {} // 두번째 방법
}

 

이해를 돕기 위해 Java 코드를 첨부한다.

class Parent {
	int x;
	public Parent(int _x) {
    	super(_x * _x);
	}
}

class Child extends Parent {
	public Child(int _y) {
		super(_y * _y);
	}
}

 

 

생성자 버전별 특징

Solidity 언어는 현재 계속해서 다음 버전으로 업그레이드 해서 출시(Release)하고 있다. 짧은 기간에 계속 업그레이드 중이고, 출시되는 각 버전마다 사용법이 조금씩 다른 부분이 있다. Solidity의 생성자(Constructor)를 정의하는 방법도 차이가 있으므로, 다른사람이 만들어놓은 스마트 컨트랙트를 올바르게 이해하려면, 최신버전뿐만 아니라 이전버전의 방법도 알아두는 것이 좋다.

 

solidity version 0.5.0 이상

생성자 이름은 constructor이어야 한다.

 

 

solidity version 0.4.22 이상

생성자 이름이 constructor이어도 된다. 생성자 이름이 계약이름과 동일하게 사용되는 문법(syntax)은 앞으로 사용되지 않을 것(deprecated)이다.

pragma solidity ^0.4.22
contract A {
 	uint public a;
 	constructor(uint _a) internal {
		a = _a;
 	}
}

contract B is A(1) {
 	constructor() public {
 	}
}

 

 

solidity version 0.4.21 이하

생성자 이름은 계약이름과 동일해야 한다.

pragma solidity ^0.4.11
contract A {
	uint public a;
	function A(uint _a) internal {
		a = _a;
	}
}

contract B is A(1) {
	function B() public {
	}
}