인스턴스 : 주로 하나의 컨트랙트에서 다른 컨트랙트로 접근할 때 쓰임.
e.g) A와 B 컨트랙트가 있다고 가정하였을 때, B에서 A 함수나 변수로 접근하여 사용하고 싶다면 A 인스턴스를 만들어 B 컨트랙트 안에서 사용하면 됨
컨트랙트 이름 인스터스의 이름 = new 컨트랙트 이름();
contract B{ A instance = new A(); }
// SPDX-License-Identifier:GPL-30
pragma solidity >= 0.7.0 < 0.9.0;
contract A{
uint256 public a = 5;
function change(uint256 _value) public {
a = _value;
}
}
contract B{
A instance = new A();
function get_A() public view returns(uint256) {
return instance.a();
}
function change_A(uint256 _value) public {
instance.change(_value);
}
}
B 컨트랙트에서 A 컨트랙트에 접근하여 변수 a와 change 변수 사용해보기.
A를 B 컨트랙트에서 인스턴스 화 하기.
접근할 때는 .을 붙여서 이동 e.g) instance.change(_value)
변수를 접글할 때는 ()을 붙여줘야 리턴이 됨
+) instance 는 A 스마트 컨트랙의 분신과 같은 존재.
즉 A를 따로 배포하고, 인스턴스 A를 스마트컨트랙트 B를 통해서 배포한다고 가정하였을때,
이 두개의 컨트랙트는 완전히 다르다.그렇기 때문에, instance를 만들어서 변수 a의 값을 변경한다해도, 스마트컨트랙 A 자체만 따로 배포한곳에는 값에 영향을 주지가 않.
constructer : 스마트 컨트랙트가 생성 또는 배포, 그리고 인스턴스화 될 때 초기값을 설정해주는 용도로 사용됨.
// SPDX-License-Identifier:GPL-30
pragma solidity >= 0.7.0 < 0.9.0;
contract A{
string public name;
uint256 public age;
constructor(string memory _name, uint256 _age){
name = _name;
age = _age;
}
function change(string memory _name, uint256 _age) public {
name = _name;
age = _age;
}
}
contract B{
A instance = new A("Alice", 52);
function change(string memory _name, uint256 _age) public {
instance.change(_name,_age);
}
function get() public view returns(string memory, uint256) {
return (instance.name(), instance.age());
}
}
A 컨트랙트에 constructor가 있음.
생성자를 통해서 파라미터를 받아, name과 age에 값을 넣어주고 있음.
컨트랙트 B에 "Alice", 52가 있는데 이것은 A를 인스턴스화 하기 위해서(생성하기 위해서) 필요한 초기 값.
get 함수 -> 여러개의 리턴을 하기에, returns 괄호 부분에 리턴하고자 하는 타입을 써줌
chagnge 함수 -> 컨트랙트 A의 change를 통해서, 생성자에서 설정한 age, name을 변경함을 알 수 있음.
상속 받을 컨트랙트 is 상속 주는 스마트 컨트랙트 { //.... }
// SPDX-License-Identifier:GPL-30
pragma solidity >= 0.7.0 < 0.9.0;
contract Father{
string public familyName = "Kim";
string public givenName = "Jung";
uint256 public money = 100;
constructor(string memory _givenName) public {
givenName = _givenName;
}
function getFamilyName() view public returns(string memory){
return familyName;
}
function getGivenName() view public returns(string memory){
return givenName;
}
function getMoney() view public returns(uint256){
return money;
}
}
contract Son is Father("James"){
}
Son이 Father의 것을 상속받는데, 컴파일 후 배포를 하면 Father의 스마트 컨트랙트 변수와 함수들을 모두 받아서 사용이 가능하다.
Father에 constructor를 넣어 givenName으로,
상속 받을 컨트랙 is 상속 주는 스마트 컨트랙 (파라미터 쓰기) {
//....
}
이런식으로 파라미터를 넣어 줌으로써, 이름을 변경할 수 있다.
overriding : 상속받은 함수를 다르게 변경 ( 상속받은 함수를 덮어 씌우기 )
// SPDX-License-Identifier:GPL-30
pragma solidity >= 0.7.0 < 0.9.0;
contract Father{
string public familyName = "Kim";
string public givenName = "Jung";
uint256 public money = 100;
constructor(string memory _givenName) public {
givenName = _givenName;
}
function getFamilyName() view public returns(string memory){
return familyName;
}
function getGivenName() view public returns(string memory){
return givenName;
}
function getMoney() view public virtual returns(uint256){
return money;
}
}
contract Son is Father("James"){
uint256 public earning = 0;
function work() public {
earning += 100;
}
function getMoney() view public override returns(uint256){
return money+earning;
}
}
getMoney 부분을 오버라이딩 하는데,
function getMoney() view public virtual returns(uint256){ return money; }
아버지 컨트랙트에 virtual을 명시해줘서, 자식 컨트랙트에서 오버라이팅을 할 것임을 알려줘야 함.
work 함수를 돌리면 earning 100씩 증가하고, getMoney를 누르면 아버지에게 받은 돈 money와 아들이 번 돈 earning이 합쳐져 아들의 재산을 보여줌.
+) 두 개 이상 상속 할 때
// SPDX-License-Identifier:GPL-30
pragma solidity >= 0.7.0 < 0.9.0;
contract Father{
uint256 public fatherMoney = 100;
function getFatherName() public pure returns(string memory){
return "KimJung";
}
function getMoney() public view virtual returns(uint256){
return fatherMoney;
}
}
contract Mother{
uint256 public motherMoney = 500;
function getMotherName() public pure returns(string memory){
return "Leesol";
}
function getMoney() public view virtual returns(uint256){
return motherMoney;
}
}
contract Son is Father, Mother {
function getMoney() public view override(Father,Mother) returns(uint256){
return fatherMoney+motherMoney;
}
}
event : 블록체인 네트워크의 블록에 특정값을 기록하는 것
로그를 사용하여, 블록에 각인시키는 것은 일반적으로 string이나 다른 값들을 스마트 컨트랙트에 저장하는 것보다 효율적이다.
event info(string name, uint256 money);
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
contract lec13 {
event info(string name, uint256 money);
function sendMoney() public {
emit info("Chae", 1000);
}
}
logs 부분에 info 이벤트가 잘 나왔음을 확인 가능.
블록 안에 저장이 되었기에 언제든지 들고 와서 쓸 수 있음
indexed를 써줌으로써 블록들안에 출력된 이벤트들을 필터하여 저희가 원하는 이벤트만을 가지고 올 수 있다.
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
contract lec14 {
event numberTracker(uint256 num, string str);
event numberTracker2(uint256 indexed num, string str);
uint256 num =0;
function PushEvent(string memory _str) public {
emit numberTracker(num,_str);
emit numberTracker2(num,_str);
num ++;
}
}
필터를 하려고 하는 파라미터값에 indexed만 써주면 된다.
// SPDX-License-Identifier:GPL-30
pragma solidity >= 0.7.0 < 0.9.0;
contract Father {
event FatherName(string name);
function who() public virtual{
emit FatherName("Spider");
}
}
contract Mother {
event MotherName(string name);
function who() public virtual{
emit MotherName("Gwen");
}
}
contract Son is Father{
event sonName(string name);
function who() public override{
super.who();
emit sonName("me")
}
}
son 컨트랙트는 father 컨트랙트의 who를 상속받아 오버라이딩 하는것을 볼 수 있다.
son 컨트랙트는, 아버지의 FatherName 이벤트를 그대로 유지하고, 자신의 sonName 이벤트를 추가했다.
만약, Son 컨트랙트 부분의 오버라이딩한 함수 who 안에 단순히 FatherName 이벤트 한 줄만 쓰는게 아니고, 여러줄의 코드를 써야할 때, 매우 번거로워진다.
이 때 super를 쓰면, 그대로 Father 컨트랙트의 이벤트를 들고 올 수 있다.
+) 상속의 순서
// SPDX-License-Identifier:GPL-30 pragma solidity >= 0.7.0 < 0.9.0; contract Father { event FatherName(string name); function who() public virtual{ emit FatherName("spider"); } } contract Mother { event MotherName(string name); function who() public virtual{ emit MotherName("gwen"); } } contract Son is Father, Mother{ function who() public override(Father,Mother){ super.who(); } }
Son 이라는 스마트컨트랙은 Father 와 Mother를 상속받앗다.
who 함수에 오버라이딩을 하여서, super.who() 를 해줌.
그러면 여기서 Father 와 Mother 누구의 것이 상속이 될까요?
정답은 Mother의 것이 상속되어서 gwen 이 반환됩니다.
왜 Father 이 아니라 Mother 인걸까요?
정답은 Son is Father , Mother 이기 때문. 즉 Mother 두번째 (최신) 으로 상속 받았기에 그렇다.