今回はcontractの作成から継承までを解説
すこしでもプログラミングに触れている人なら
「クラスと一緒で、C言語に近い継承を持っている」
と伝えると、だいたい言語仕様が理解できるでしょう。
ではcontract(クラス)について理解しましょう。
Version Pragma
ちょっとcontractの話の前に
Version Pragmaについて理解をしておこう
Version Pragmaは
コンパイラを指定するわけではないです。
あくまで、これは注釈であり
また、指定してもコンパイラを変更できません。
Pragmaを指定することで、記入したバージョンでのチェックが動きます。
現在想定したコンパイラで実装し、それが、シンタックスなどの内容が間違っていないかを
チェックしてくれます。
下記を例にすると
pragma solidity >= 0.4.0 < 0.7.0;
contract testContract {
}
Solidity の 0.4.0 以上、0.7.0 未満のバージョンとの互換性があるソースである
Solidity の 0.4.0 以上、0.7.0 未満のバージョンでのコーディングでのエラーが
ないかチェックせよ・・・という意味になる
コンパイル指定ではない、ことを理解しておこう
インスタンス生成
solidityにおいてのインスタンス(contract)生成方法は
各種言語のクラス生成と同じで
newキーワードを利用してインスタンスを作成(デプロイ)します
コントラクト contract(インスタンス)生成 new キーワード
先にも述べたが
コントラクト(インスタンス)の生成には
newキーワードを使って生成する
このコンストラクト作成には
GASが必要になるのだが・・・その内容はまた別の機会で説明する
solidity:コンストラクタ
コンストラクタとは
インスタンスが生成される場合に
初回だけ実施されるメソッドである
また、コンストラクタが宣言されていない場合には
自動でデフォルトコンストラクタが作成される
通常の言語(javaなど)ではコンストラクタは
インスタンスの生成時に毎回実行されるが
solidityは他の言語と違い、コンストラクタの動きが違うことを覚えておこう
solidityのコンストラクタは、デプロイ時に一度だけ実行される
solidityのコンストラクタは、インスタンス生成時に「毎回実行されない」
一般的なインスタンスの生成の違いについて理解する

solidityでのインスタンス作成は
通常の言語とは動きが違う
これにはブロックチェーンが関わってくる
そもそもsolidityはブロックチェーンかつ、スマートコントラクトの言語である
いままでのプログラミングであるオブジェクト思考でのプログラミングと概念が違う
コントラクトの作成=インスタンス生成には、デプロイといった動きが必ず発生することを理解して欲しい
いままでの言語のように、メモリ空間上にインスタンス化し再利用する物とは違う
インスタンスの作成にはブロックチェーンにデプロイするため
GASも発生する
solidity:継承 is
solidityでも他の言語同様に継承ができる
is キーワードを使って継承する
継承では
- 単一継承
- 多重継承
の両方が可能
単一継承
下記のような単一継承が可能
contract objectA {
// 実装内容・・・
}
contract objectB is objectA {
// 実装内容・・・
}
これは単純な継承です
contract objectA {
// 実装内容・・・
}
contract objectB is objectA {
// 実装内容・・・
}
contract objectC is objectA {
// 実装内容・・・
}
これはobjectAを基底contractとして、派生したobjectB、objectCの
contractを作成しています。
contract objectA {
// 実装内容・・・
}
contract objectB is objectA {
// 実装内容・・・
}
contract objectC is objectB {
// 実装内容・・・
}
こちらの継承もできるが
少し複雑になるため
あまり、使わないけど、こういうことも可能です。
多重継承
contract objectA {
// 実装内容・・・
}
contract objectB is objectA {
// 実装内容・・・
}
contract objectC is objectA {
// 実装内容・・・
}
contract objectD is objectA, objectB, objectC {
// 実装内容・・・
}
javaを主に使っていた私からすると
あまり利用したくない機能です
javaは単一継承しか許されていない・・・
注意点として、
objectDはobjectAも継承しているところですかね
私はあまり慣れないです・・・・
solidity:抽象コントラクト abstract
抽象コントラクト(contract)とは、抽象であるため
実態を持たない(インスタンスの作成ができない)
抽象コントラクトを利用するには
利用するコントラクト側で継承する必要がある
また、抽象コントラクトで指定した
メソッドは、継承側のコントラクトで
メソッドの実装が強制される
現在のsolidityのバージョンではabstractのキーワードの指定は
必要なく
実装を持たない、メソッドのみのcontractを作成すれば良い
pragma solidity >=0.4.16 <0.9.0;
//抽象contractでは、メソッドの型のみ宣言する
contract AbstractContract {
function getValue() public view returns(uint);
}
//実態側で抽象contractを継承し、指定されたメソッドの実態を作成する
contract Calculator_implementation is AbstractContract {
function getValue() public view returns(uint) {
uint calcObjA = 10;
uint calcObjB = 20;
uint retValue = calcObjA * calcObjB;
return retValue;
}
}
solidity:インターフェース interface
抽象コントラクトと似ているが
変数を持つことができず
メソッドの宣言のみのコントラクト
利用には利用側のコントラクトで継承する
利用側のコントラクトでは
メソッドの実態の作成が強制される
特徴として
- 関数を実装することはできない
- 他のインターフェースから継承できる
- 宣言されたメソッドはすべてexternalでないといけない
- コンストラクターを作成できない
- 状態変数(ステート変数)を保持できない
javaでのstaticなグローバル変数みたいな物です。
ただし、storegeというブロックチェーン上に格納され、ブロックチェーン上で利用することから、GASも高くなる要因の一つ
pragma solidity ^0.8.0;
interface Calculator {
function getResult() external view returns(uint);
}
//インターフェースを継承
contract Calculator_implementation is Calculator {
//インターフェースで宣言されたメソッドの実態を実装する
function getResult() external view returns(uint){
uint calcObjA = 100;
uint calcObjB = 5;
uint result = a % b;
return result;
}
}
抽象コントラクト(contract またはクラス)とインターフェースの違いとは?
ちょっと、プログラミングで理解できていない人もいるため
抽象コントラクト(contract またはクラス)とインターフェースの違いに触れよう
抽象コントラクト
抽象コントラクトは
is-aの関係の物を示すために使います。
「is-aの関係」といっても
ピンとこないですね
抽象的なものを表現することから抽象コントラクトなのですが
人も、犬も、猫も、動物で表せます。
トラック、セダン、RVは車で表せますね
言い換えると
人、犬、猫 → 動物 である(is-a)
抽象として表した場合に「動物」の一括りで表せます
トラック、セダン、RV → 車 である(is-a)
抽象として表した場合に「車」の一括りで表せます
インターフェース
インターフェースとは、振る舞いのみを宣言したコントラクトであり
抽象コントラクトと対比して話をすると
異なった物の振る舞いのみでグルーピングすることが可能になる
元々は違った振る舞いをグループにまとめ
多重継承のためにインターフェースを使う場合が多い
solidity:ライブラリ library
solidityには再利用可能であるが、状態を持たない、contractがある
libraryキーワードで宣言する
javaでいうstaticクラス的なものですね
ちょうどいい例、いや、ライブラリがあります
こちらのソースを確認すればわかりますが
文字列関連の各種処理をライブラリとして作成しています。
//https://github.com/Arachnid/solidity-stringutils/blob/master/src/strings.sol のソースから
//抜粋
pragma solidity ^0.8.0;
//libraryキーワードを使用して、ライブラリであることを宣言
library strings {
struct slice {
uint _len;
uint _ptr;
}
function memcpy(uint dest, uint src, uint len) private pure {
// Copy word-length chunks while possible
for(; len >= 32; len -= 32) {
assembly {
mstore(dest, mload(src))
}
dest += 32;
src += 32;
}
// Copy remaining bytes
uint mask = type(uint).max;
if (len > 0) {
mask = 256 ** (32 - len) - 1;
}
assembly {
let srcpart := and(mload(src), not(mask))
let destpart := and(mload(dest), mask)
mstore(dest, or(destpart, srcpart))
}
}
//以下省略
使い方は
using キーワードを使い使いたいデータに対して指定する
pragma solidity ^0.8.0;
import 'ds-test/test.sol';
//ライブラリをインポート
import './strings.sol';
contract StringsTest is DSTest {
//利用したいデータに対して、指定する、今回は全て
using strings for *;
function abs(int x) private pure returns (int) {
if(x < 0)
return -x;
return x;
}
function sign(int x) private pure returns (int) {
return x == 0 ? int(0) : (x < 0 ? -1 : int(1));
}
function assertEq0(string memory a, string memory b) internal {
assertEq0(bytes(a), bytes(b));
}
function assertEq0(strings.slice memory a, strings.slice memory b) internal {
assertEq0(a.toString(), b.toString());
}
function assertEq0(strings.slice memory a, string memory b) internal {
assertEq0(a.toString(), b);
}
function testSliceToString() public {
string memory test = "Hello, world!";
assertEq0(test, test.toSlice().toString());
}
function testBytes32Len() public {
bytes32 test;
for(uint i = 0; i <= 32; i++) {
assertEq(i, test.len());
test = bytes32((uint(test) / 0x100) | 0x2000000000000000000000000000000000000000000000000000000000000000);
}
}
//以下省略
まとめ
solidtyのcontractは他の言語のクラスに近いと説明した
しかし、他の言語と大きく違うのは
ブロックチェーン上での管理されるもの、また、メモリ上に利用する物
インスタンス化にはブロックチェーン上に
デプロイが伴うことなど
いくつかの違いがあり
WEB3.0 = ブロックチェーン
を理解する上での、難しいところであり
いままでの言語とは少し違うことを理解しないといけない
また、現在最新の書籍を見つけることは難しく
WEBでの情報が全てなので
その点でも理解しにくい部分が多い
それ以外にも、GASの計算も必要になるため
何かと初心者には難しいが
だからこそ、今後のWEB3.0の技術者が必要になった場合
(確実に足りなくなると思うが・・・)
少しでも役立てて欲しい。
わたしもまだ勉強中ではあるが
できるだけ詳しく説明できれば(初心者にも)
と思う