전 포스트에서
기본적인 값 자료형에 다뤄봤다.
이번시간도 자료형이지만
참조 자료형에 대해 알아보자.
가장 먼저 Struct 변수, 구조체에 대해
그리고 constructor()까지 알아보자.
// 기본적인 Struct 구조는 이와 같다.
// 가장먼저 선언을 하고 그 안에 value형 변수들을 넣는다.
contract Ex{
struct Product {
string name;
uint256 price;
}
// 이렇게 구조체를 선언했으면 이 구조체 해당 변수는 일반 변수 선언 형태로 선언한다.
Product public mainPd;
// 하지만 네트워크에 배포할 때 초기값 설정을 위한 constructor()도 있다.
// 이는 초기 배포시에만 동작하고 그 뒤에는 사용되지 않는다.
//처음에 세팅하고 바뀔 수 없는 값들을 세팅할 때 사용한다.
uint256 public pd1Price;
constructor(uint _mainPdPrice) {
mainPdPrice = _mainPdPrice);
}
// 구조체 필드 선언
// 방법1
function initProduct() public {
Product memory firstPd;
firstPd = Product("pd1", 10);
}
//방법2
function setMainPd(string _name, uint256 price) public {
mainPd.name = _name;
mainPd.price = _price;
}
function getMainPdPridce() public view returns(uint256) {
return mainPd.price
}
}
그 다음은 enum이다.
사용 경우는 컨트랙트의 진행 상태같은 것을 볼 때 사용한다.
유저나 개발자가 명확히 이해하도록 한다.
//(생략)
contract Ex{
//여기에는 변수가 아니라 실제로 들어갈 데이터를 넣는다.
// 경매로 예를 든다.
enum Status {
Not sale,
Auction,
Sales,
Bid,
Sold
}
//경매 상태 변수를 선언한다.
Status public auctionStatus;
// enum의 Auction필드를 통해 경매 시작을 알아낸다.
function auctionStart() public{
auctionStatus = Status.Auction;
}
// 팔렸는지 보고싶다면
function sold() public {
auctionStatus = Status.Sold;
}
// 이렇게 직관적으로 확인하고 싶을 때 enum이라는 자료형을 사용한다.
// 코드의 가독성 향상을 위해 사용된다.
}
프로그래밍 중 또 가장 중요한 요소인 배열이다.
솔리디티에서 어떻게 사용되는지 알아보자
contract Ex{
uint[] public uintList = [1, 2, 3, 4] //이런식으로 사용한다.
uint[4] public uint4List = [1, 2, 3, 4] // 개수를 미리 정함.
// 리스트 응용 메서드
// 하지만 이 경우에는 리스트가 동적할당 돼야하고
// 메서드를 함수 안에서 사용할 수 있다.
// 1. 배열끝에 요소 추가할 경우
function addToArray() public {
uintList.push(5); // [1, 2 ,3 ,4, 5]
}
// 2. 요소 제거하는 경우
function popToArray() public view returns(uint) {
uint num = uintList.pop();
return num;
// pop()은 요소를 제거하며, 그 값을 리턴한다.
// 결과 [1, 2, 3, 4]
}
// 3. 요소 조회
// 조회만 할 뿐 리스트 자체에 영향을 주지 않는다.
int public secondData = intList[1]; // 2
// 4. delete 이용
// [1, 2, 3, 4]의 리스트에서 2라는 값을 지우고 싶다면
function removeElement(uint index) public {
delete intList[index]; // 인덱스의 값을 0으로 초기화, 완전 소거 X
}
// Struct형태도 동일함.
Struct Product {
string name;
uint256 price;
}
Product public mainPd;
Product[] public pdList;
pdList.push(mainPd);
// 이런식으로 구조체 배열 선언과, push()함수 이용이 가능하다.
}
mapping 키워드 자주 쓴다.
key-value 형태이며
주로 잔액 조회에 자주 이용된다.
이때 키는 사용자 주소고 밸류는 잔액이 될 수 있다.
contract Ex{
mapping(address => uint256) public balance;
// 그래서 key값이 중복 발생이 일어나지 않음.
// mapping 형태 변수 선언은 다음과 같이 한다.
// 주소는 임의로 이더스캔에서 하나 갖고옴.
balance["0x95222290DD7278Aa3Ddd389Cc1E1d165CC4BAfe5"] = 1000;
// 잔액을 조회한다면
uint256 myBalance = balance["0x95222290DD7278Aa3Ddd389Cc1E1d165CC4BAfe5"]; // 잔액: 1000
// 동일한 키에 대응하는 다른 값을 입력하면 업데이트되는 형식이다.
balance["0x95222290DD7278Aa3Ddd389Cc1E1d165CC4BAfe5"] = 10;
myBalance = balance["0x95222290DD7278Aa3Ddd389Cc1E1d165CC4BAfe5"]; // 잔액 : 10
// 다른 주소를 넣게되면
balance["0x73f7b1184B5cD361cC0f7654998953E2a251dd58"] = 50; // 새로운 이 주소에 대한 잔액이 추가된다.
// 결국 중복이 발생하지 않는다.
// 같은 키면 업데이트가 되는 방식이기 때문이다.
}
변수가 중복될 때 어떻게 동작하는지 보자.
컨트랙트 배포와 함수 호출은 따로 권한다.
contract Ex {
uint private data = 10; // 상태 변수로 Storage에 저장된다.
// 상태 변수를 처리하기 때문에 view를 사용해 값을 리턴한다.
function fn1() public view returns(uint){
return data; //10
}
// 지역 변수를 사용하기 때문에 pure를 사용해 값을 리턴한다.
function fn2() public pure returns(uint){
uint8 data = 5;
return data; // 5
}
// 변수가 중복될 때 지역 변수의 값으로 리턴된다.
}
주소에도 형태가 있다.
contract Ex{
address public failUser = 0xfca28ad8fca6033e37303f94fe0120c61f62fe41f0c7ad8c4f3fe4e0472cb1d0;
address public user = 0x73f7b1184B5cD361cC0f7654998953E2a251dd58;
// 소문자로만 된 주소와, 대소문자가 섞인 주소가 있다.
// 이대로 remix에서 컴파일을 진행하면
// 오류가 뜬다.
// 어카운트 checkSum이 failUser는 진행되지 않아서 솔리디티에서 사용할 수 없다.
// 그래서 항상 솔리디티에서 주소를 사용할 때 checkSum을 거친 데이터만 사용할 수 있다.
}
말 그대로 돈과 관련있는 키워드다.
contract Ex{
// 이더를 주고 받는 CA, EOA는 컨트랙트 상에 payable을 명시해야 한다.
// 함수 또한 마찬간지다.
address public user = 0x73f7b1184B5cD361cC0f7654998953E2a251dd58;
address payable public payable_user = payable(user);
// 간단한 이더 전송 함수다. payable에 집중하자.
function sendETH() public payable{
// user.transfer(10**18); 이것은 오류댜 왜냐하면 user선언시 payable넣지 않음
payable.user.transfer(10**18); // 잘 전송된다.
}
// address 타입 특징으로 바로 잔액을 구할 수 있다.
function getBalanceETH() public view returns(uint256){
return user.balance;
}
}
이 키워드는 해당 컨트랙트를 가릴킬 수 있다.
contract Ex{
uint public data = 5;
// 이 해당 컨트랙트의 잔액을 구하고 싶다면
function getBalance() public view returns(uint256) {
return address(this).balance;
}
function externalFunc() external {
data = 15;
}
function internalFunc() internal {
// 이 함수 내부에서 externalFunc()를 호출하면 에러가 발생한다.
// externalFunc(); => Error!!!!
// 그렇다면 this를 이용한다.
this.externalFunc()
}
}
또 이렇게 다양한 형태의 자료형을 살펴봤다.