Solidity তে Inheritance এবং Interfaces ব্যবহার করা হয় কোড পুনঃব্যবহারযোগ্যতা, কাঠামো এবং মডুলারিটি নিশ্চিত করার জন্য। এই দুটি কনসেপ্ট সাধারণত অ্যাবস্ট্র্যাকশন এবং অন্যান্য কন্ট্রাক্টের সাথে ইন্টারঅ্যাকশন তৈরির জন্য ব্যবহৃত হয়। Solidity তে ইনহেরিটেন্সের মাধ্যমে এক কন্ট্রাক্ট অন্য কন্ট্রাক্টের ফাংশন এবং বৈশিষ্ট্য গ্রহণ করতে পারে, এবং ইন্টারফেসের মাধ্যমে কন্ট্রাক্টের মধ্যে নির্দিষ্ট ফাংশন কেবল ঘোষণা করে, তাদের বাস্তবায়ন করা হয় অন্যান্য কন্ট্রাক্টে।
১. Inheritance (ইনহেরিটেন্স)
Inheritance হল একটি কন্ট্রাক্টের ক্ষমতা অন্য একটি কন্ট্রাক্ট থেকে বৈশিষ্ট্য (properties) এবং ফাংশন (functions) গ্রহণ করার। Solidity তে একাধিক কন্ট্রাক্ট একটি প্রধান কন্ট্রাক্টের বৈশিষ্ট্য এবং ফাংশন হেরিট করতে পারে, যা কোড পুনঃব্যবহার সহজ করে এবং স্মার্ট কন্ট্রাক্ট ডেভেলপমেন্টে মডুলারিটির সুযোগ দেয়।
Inheritance Syntax (ইনহেরিটেন্স সিনট্যাক্স)
pragma solidity ^0.8.0;
contract BaseContract {
uint public baseValue;
constructor(uint _baseValue) {
baseValue = _baseValue;
}
function getBaseValue() public view returns (uint) {
return baseValue;
}
}
contract DerivedContract is BaseContract {
uint public derivedValue;
constructor(uint _baseValue, uint _derivedValue) BaseContract(_baseValue) {
derivedValue = _derivedValue;
}
function getDerivedValue() public view returns (uint) {
return derivedValue;
}
}- BaseContract হল একটি বেস কন্ট্রাক্ট, যেখানে
baseValueভেরিয়েবল এবং একটি কনস্ট্রাক্টর ফাংশন রয়েছে। - DerivedContract হল একটি ডেরাইভড কন্ট্রাক্ট যা
BaseContractথেকে ইনহেরিট করেছে। এটিbaseValueএবংderivedValueভেরিয়েবলও ধারণ করে। DerivedContractকন্ট্রাক্টেBaseContractএর কনস্ট্রাক্টর কল করার জন্য,BaseContract(_baseValue)ব্যবহার করা হয়েছে।
Multiple Inheritance (একাধিক ইনহেরিটেন্স)
Solidity একাধিক কন্ট্রাক্ট থেকে ইনহেরিটেন্স সমর্থন করে, তবে যখন একাধিক কন্ট্রাক্ট একই নামের ফাংশন বা ভেরিয়েবল দেয়, তখন এটি diamond problem তৈরি করতে পারে। এই সমস্যা এড়ানোর জন্য, Solidity তে linearization পদ্ধতি ব্যবহৃত হয়।
pragma solidity ^0.8.0;
contract A {
function sayHello() public pure returns (string memory) {
return "Hello from A";
}
}
contract B is A {
function sayHello() public pure returns (string memory) {
return "Hello from B";
}
}
contract C is A {
function sayHello() public pure returns (string memory) {
return "Hello from C";
}
}
contract D is B, C {
// D inherits sayHello() from B and C, which may cause issues
}এখানে, D কন্ট্রাক্টে B এবং C থেকে sayHello() মেথড ইনহেরিট করা হবে, যা diamond problem সৃষ্টি করতে পারে। এই সমস্যা এড়ানোর জন্য, Solidity নির্দিষ্টভাবে কোন কন্ট্রাক্টের ফাংশন নিতে হবে তা উল্লেখ করার জন্য কন্ট্রাক্ট লিনিয়ারাইজেশন ব্যবহার করে।
২. Interfaces (ইন্টারফেসেস)
Interfaces হল একটি কন্ট্রাক্টের সঠিক স্ট্রাকচার বা কাঠামো যেটি কেবলমাত্র ফাংশনের ঘোষণার জন্য ব্যবহৃত হয়, কিন্তু তাদের বাস্তবায়ন কন্ট্রাক্টে করা হয়। ইন্টারফেসের মাধ্যমে আপনি বিভিন্ন কন্ট্রাক্টের মধ্যে স্ট্যান্ডার্ডাইজড ইন্টারঅ্যাকশন তৈরি করতে পারেন। ইন্টারফেসে কোন কনস্ট্রাক্টর, স্টোরেজ ভেরিয়েবল বা ফাংশন বডি থাকতে পারে না—তবে সেগুলোর সিগনেচার থাকতে হবে।
Interface Syntax (ইন্টারফেস সিনট্যাক্স)
pragma solidity ^0.8.0;
interface IToken {
function transfer(address recipient, uint amount) external returns (bool);
function balanceOf(address account) external view returns (uint);
}
contract MyToken is IToken {
mapping(address => uint) public balances;
function transfer(address recipient, uint amount) public override returns (bool) {
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount;
balances[recipient] += amount;
return true;
}
function balanceOf(address account) public view override returns (uint) {
return balances[account];
}
}- IToken হল একটি ইন্টারফেস, যা
transferএবংbalanceOfনামের দুটি ফাংশন ঘোষণা করেছে। ইন্টারফেসে কেবল ফাংশনের সিগনেচার থাকবে, কিন্তু তাদের বাস্তবায়ন কন্ট্রাক্টে থাকতে হবে। - MyToken কন্ট্রাক্টে
ITokenইন্টারফেসের ফাংশনগুলি বাস্তবায়িত করা হয়েছে।overrideকিওয়ার্ড ব্যবহার করা হয়েছে, কারণMyTokenইন্টারফেসের ফাংশনগুলি অতিক্রম করছে (override করছে)।
Interface এর সুবিধা
- স্বচ্ছতা: ইন্টারফেস ব্যবহার করে আপনি সিস্টেমের মধ্যে পরিষ্কার স্ট্যান্ডার্ড ইন্টারঅ্যাকশন তৈরি করতে পারেন।
- স্ট্যান্ডার্ডাইজেশন: একাধিক কন্ট্রাক্টের মধ্যে একই ফাংশন সিগনেচার ব্যবহার করা সহজ করে তোলে, যেমন ERC-20 বা ERC-721 টোকেন স্ট্যান্ডার্ড।
Interface Example: ERC-20 Token
pragma solidity ^0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
}এখানে, IERC20 ইন্টারফেস ERC-20 টোকেন স্ট্যান্ডার্ডের প্রাথমিক ফাংশনগুলোর সিগনেচার ঘোষণা করা হয়েছে। যেকোনো কন্ট্রাক্ট যা IERC20 ইন্টারফেসকে অনুসরণ করবে, তার মধ্যে এই ফাংশনগুলোর বাস্তবায়ন থাকতে হবে।
সারাংশ
Inheritance এবং Interfaces Solidity তে স্মার্ট কন্ট্রাক্টের পুনঃব্যবহারযোগ্যতা, স্ট্রাকচার, এবং স্ট্যান্ডার্ডাইজেশন নিশ্চিত করতে ব্যবহৃত হয়। Inheritance এর মাধ্যমে একটি কন্ট্রাক্ট অন্য কন্ট্রাক্টের বৈশিষ্ট্য ও ফাংশন গ্রহণ করতে পারে, যা কোডের পুনঃব্যবহার এবং মডুলারিটি সহজ করে। Interfaces কন্ট্রাক্টের মধ্যে ফাংশনের সিগনেচার ঘোষণা করে, এবং এর মাধ্যমে বিভিন্ন কন্ট্রাক্টের মধ্যে মানক ইন্টারঅ্যাকশন নিশ্চিত করা যায়। Solidity তে এই কনসেপ্ট দুটি ব্যবহার করে কোডের কার্যকারিতা, নিরাপত্তা এবং সামঞ্জস্যতা উন্নত করা যায়।
Contract Inheritance হল একটি অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিং কনসেপ্ট যা স্মার্ট কন্ট্রাক্টের মধ্যে কোড পুনঃব্যবহার এবং ফাংশনালিটির শেয়ারিং সম্ভব করে। Solidity তে inheritance এর মাধ্যমে একটি কন্ট্রাক্ট (child contract) অন্য কন্ট্রাক্ট (parent contract) থেকে ফাংশন এবং প্রপার্টি গ্রহণ করতে পারে। এটি কোডের পুনঃব্যবহারযোগ্যতা বৃদ্ধি করে এবং কন্ট্রাক্টগুলোর মধ্যে কার্যকারিতা ভাগ করে নিয়ে আসতে সাহায্য করে।
Solidity তে ইনহেরিটেন্স ব্যবহার করে, আপনি একটি কন্ট্রাক্টের বৈশিষ্ট্য এবং আচরণ অন্য কন্ট্রাক্টে উত্তরাধিকারসূত্রে গ্রহণ করতে পারেন। এটি আপনাকে একটি বড়, জটিল প্রোগ্রাম বা অ্যাপ্লিকেশন তৈরি করার সময় কোডের পরিমাণ কমিয়ে আনতে এবং কোডের কাঠামোকে আরও সুষম এবং সুসংগঠিত করতে সহায়তা করে।
1. Solidity তে Inheritance এর কাজ
Solidity তে ইনহেরিটেন্সের মাধ্যমে আপনি এক কন্ট্রাক্টের ফাংশন এবং প্রপার্টি অন্য কন্ট্রাক্টে গ্রহণ করতে পারেন। এর মাধ্যমে আপনি পুনরায় একই কোড না লিখে পূর্বের কন্ট্রাক্টের বৈশিষ্ট্য এবং আচরণ ব্যবহার করতে পারেন।
- Single Inheritance: একটি কন্ট্রাক্ট অন্য একটি কন্ট্রাক্ট থেকে ফাংশন এবং প্রপার্টি গ্রহণ করবে।
- Multiple Inheritance: একটি কন্ট্রাক্ট একাধিক কন্ট্রাক্ট থেকে ফাংশন এবং প্রপার্টি গ্রহণ করতে পারে।
2. Single Inheritance Example
pragma solidity ^0.8.0;
contract Parent {
uint public value;
constructor(uint _value) {
value = _value;
}
function setValue(uint _value) public {
value = _value;
}
}
contract Child is Parent {
string public name;
constructor(uint _value, string memory _name) Parent(_value) {
name = _name;
}
function getName() public view returns (string memory) {
return name;
}
}ব্যাখ্যা:
Parentকন্ট্রাক্ট একটিvalueপ্রপার্টি ধারণ করে এবং সেটি আপডেট করার জন্য একটিsetValueফাংশন প্রদান করে।Childকন্ট্রাক্টParentকন্ট্রাক্ট থেকে ইনহেরিট করছে এবং এরvalueপ্রপার্টি এবংsetValueফাংশন পেয়ে যাচ্ছে।Childকন্ট্রাক্টের কনস্ট্রাক্টরParentকন্ট্রাক্টের কনস্ট্রাক্টরও কল করছে।
3. Multiple Inheritance Example
Solidity তে মাল্টিপল ইনহেরিটেন্সে একাধিক কন্ট্রাক্ট থেকে ফাংশন এবং প্রপার্টি গ্রহণ করা যেতে পারে।
pragma solidity ^0.8.0;
contract A {
function functionA() public pure returns (string memory) {
return "Function A from Contract A";
}
}
contract B {
function functionB() public pure returns (string memory) {
return "Function B from Contract B";
}
}
contract C is A, B {
function functionC() public pure returns (string memory) {
return "Function C from Contract C";
}
}ব্যাখ্যা:
Contract Cদুইটি কন্ট্রাক্টAএবংBথেকে ইনহেরিট করছে।- এটি
functionAএবংfunctionBফাংশনগুলি ব্যবহার করতে পারবে, যেগুলিContract AএবংContract Bথেকে ইনহেরিট করা হয়েছে। Contract Cনিজের একটি নতুন ফাংশনfunctionCপ্রদান করেছে।
4. Visibility and Overriding Functions
Solidity তে ইনহেরিটেড ফাংশন এবং প্রপার্টির visibility (public, private, internal) এবং overriding (একই নামের ফাংশন পরিবর্তন) নিয়েও কাজ করা যায়।
Function Overriding Example:
pragma solidity ^0.8.0;
contract Parent {
function greet() public pure returns (string memory) {
return "Hello from Parent!";
}
}
contract Child is Parent {
// greet() ফাংশনকে override করা হচ্ছে
function greet() public pure override returns (string memory) {
return "Hello from Child!";
}
}ব্যাখ্যা:
Childকন্ট্রাক্টেgreet()ফাংশনটিParentকন্ট্রাক্ট থেকে ইনহেরিট করা হয়েছে, তবে এটি override করা হয়েছে এবংChildকন্ট্রাক্টে নতুন আচরণ দেওয়া হয়েছে।
5. Constructor Inheritance
Solidity তে, কনস্ট্রাক্টর ইনহেরিট করতে হলে, চাইল্ড কন্ট্রাক্টের কনস্ট্রাক্টরকে প্যারেন্ট কন্ট্রাক্টের কনস্ট্রাক্টর কল করতে হবে। এটি প্যারেন্ট কন্ট্রাক্টের প্রপার্টি বা ইনিশিয়াল মান সেট করার জন্য প্রয়োজনীয়।
pragma solidity ^0.8.0;
contract Parent {
uint public value;
constructor(uint _value) {
value = _value;
}
}
contract Child is Parent {
string public name;
constructor(uint _value, string memory _name) Parent(_value) {
name = _name;
}
}ব্যাখ্যা:
Childকন্ট্রাক্টParentকন্ট্রাক্টের কনস্ট্রাক্টরকে কল করেছে, যেটিvalueপ্রপার্টি ইনিশিয়ালাইজ করার জন্য ব্যবহার করা হয়েছে।
6. Super Keyword
Solidity তে super কীওয়ার্ড ব্যবহার করে আপনি প্যারেন্ট কন্ট্রাক্টের একটি ফাংশন বা প্রপার্টি কল করতে পারেন, যদি সেটি ইনহেরিটেড বা ওভাররাইড করা হয়।
pragma solidity ^0.8.0;
contract Parent {
function greet() public pure returns (string memory) {
return "Hello from Parent!";
}
}
contract Child is Parent {
function greet() public pure override returns (string memory) {
return string(abi.encodePacked(super.greet(), " and Child!"));
}
}ব্যাখ্যা:
- এখানে
super.greet()প্যারেন্ট কন্ট্রাক্টেরgreet()ফাংশনটি কল করছে এবং তার পরেChildকন্ট্রাক্টের নিজস্ব টেক্সট যুক্ত করছে।
সারাংশ
Solidity তে Contract Inheritance একটি গুরুত্বপূর্ণ ফিচার যা স্মার্ট কন্ট্রাক্টের কোড পুনঃব্যবহার এবং কার্যকারিতা ভাগ করে নেওয়ার জন্য ব্যবহৃত হয়। এটি এক কন্ট্রাক্টের ফাংশন, প্রপার্টি, এবং কনস্ট্রাক্টর অন্য কন্ট্রাক্টে ইনহেরিট করতে সাহায্য করে। Solidity তে ইনহেরিটেন্সের মাধ্যমে single inheritance এবং multiple inheritance করা সম্ভব, এবং এটি ফাংশন ওভাররাইডিং, visibility নিয়ন্ত্রণ, এবং super কীওয়ার্ড ব্যবহারের মাধ্যমে আরও উন্নত কার্যকারিতা প্রদান করে।
Solidity তে Multiple Inheritance এবং Contract Inheritance Chain এর মাধ্যমে একাধিক কন্ট্রাক্ট থেকে ফাংশন এবং প্রোপার্টি (ভেরিয়েবল) পাওয়া যায়। Solidity তে কন্ট্রাক্টগুলির মধ্যে উত্তরাধিকার (inheritance) সম্পর্ক স্থাপন করে কোড পুনঃব্যবহারযোগ্যতা, সিস্টেমের সুনির্দিষ্টতা, এবং স্থায়িত্ব বৃদ্ধি করা যায়।
এই দুটি ধারণা বুঝতে এবং সঠিকভাবে ব্যবহার করতে হলে, কন্ট্রাক্টের মধ্যে কীভাবে ইনহেরিট করা যায় এবং কিভাবে একাধিক কন্ট্রাক্টের ফাংশন এবং বৈশিষ্ট্য একত্রে ব্যবহৃত হতে পারে তা জানা প্রয়োজন।
1. Multiple Inheritance (একাধিক উত্তরাধিকার)
Solidity তে Multiple Inheritance হল একাধিক কন্ট্রাক্ট থেকে একই কন্ট্রাক্টে ফাংশন এবং প্রোপার্টি (ভেরিয়েবল) উত্তরাধিকার (inherit) করার প্রক্রিয়া। Solidity তে একাধিক কন্ট্রাক্ট থেকে ফাংশন এবং ভেরিয়েবল মিশ্রিত (combine) করা যায়, তবে এই প্রক্রিয়ায় কিছু সতর্কতা অবলম্বন করা প্রয়োজন, যেমন diamond problem (যা কিছু ক্ষেত্রে সমস্যা তৈরি করতে পারে)।
গঠন:
contract ContractA {
function functionA() public pure returns (string memory) {
return "Function A from ContractA";
}
}
contract ContractB {
function functionB() public pure returns (string memory) {
return "Function B from ContractB";
}
}
contract MyContract is ContractA, ContractB {
// ContractA এবং ContractB এর সব ফাংশন এবং প্রোপার্টি উপলব্ধ
}এখানে, MyContract কন্ট্রাক্টটি ContractA এবং ContractB কন্ট্রাক্ট থেকে ফাংশন ইনহেরিট করেছে। তাই MyContract কন্ট্রাক্টে উল্লিখিত দুটি কন্ট্রাক্টের সব ফাংশন এবং বৈশিষ্ট্য একত্রে ব্যবহার করা যাবে।
উদাহরণ:
pragma solidity ^0.8.0;
contract A {
uint public a = 10;
}
contract B {
uint public b = 20;
}
contract C is A, B {
function getSum() public view returns (uint) {
return a + b; // A এবং B থেকে ইনহেরিটেড ভেরিয়েবল
}
}এখানে, C কন্ট্রাক্টটি A এবং B কন্ট্রাক্ট থেকে a এবং b ভেরিয়েবল ইনহেরিট করেছে। getSum ফাংশনটি এই ভেরিয়েবলগুলো যোগ করে আউটপুট দেয়।
2. Contract Inheritance Chain (কন্ট্রাক্ট উত্তরাধিকার চেইন)
Contract Inheritance Chain এর মাধ্যমে একটি কন্ট্রাক্ট অন্য কন্ট্রাক্ট থেকে ইনহেরিট করা হয়, এবং এই উত্তরাধিকার চেইন এমনভাবে তৈরি হয় যে, একাধিক স্তরের কন্ট্রাক্টের মধ্যে কার্যকরী সম্পর্ক থাকে। Solidity তে এটি multilevel inheritance নামে পরিচিত, যেখানে একটি কন্ট্রাক্ট অন্য কন্ট্রাক্ট থেকে ইনহেরিট করার পর সেই কন্ট্রাক্ট আবার অন্য কন্ট্রাক্ট থেকে ইনহেরিট করতে পারে।
গঠন:
contract Parent {
function parentFunction() public pure returns (string memory) {
return "Function from Parent contract";
}
}
contract Child is Parent {
function childFunction() public pure returns (string memory) {
return "Function from Child contract";
}
}
contract Grandchild is Child {
function grandchildFunction() public pure returns (string memory) {
return "Function from Grandchild contract";
}
}এখানে, Grandchild কন্ট্রাক্টটি Child কন্ট্রাক্ট থেকে ইনহেরিট করে, যা আবার Parent কন্ট্রাক্ট থেকে ইনহেরিট করা হয়েছে। এর ফলে Grandchild কন্ট্রাক্টের কাছে Parent এবং Child কন্ট্রাক্টের সকল ফাংশন পাওয়া যাবে।
3. Diamond Problem (ডায়মন্ড প্রবলেম)
Solidity তে diamond problem একটি সমস্যা হতে পারে যখন একাধিক কন্ট্রাক্ট একই ফাংশন বা বৈশিষ্ট্য মঞ্জুর করে। একাধিক উত্তরাধিকার ব্যবহারের ক্ষেত্রে যদি দুইটি কন্ট্রাক্ট একই ফাংশন বা ভেরিয়েবল ডিফাইন করে, তবে Solidity কোন কন্ট্রাক্টের ফাংশনটি ব্যবহার করবে তা নির্ধারণ করতে পারে না।
Diamond Problem এ উদাহরণ:
pragma solidity ^0.8.0;
contract A {
function myFunction() public pure returns (string memory) {
return "Function from A";
}
}
contract B is A {
function myFunction() public pure returns (string memory) {
return "Function from B";
}
}
contract C is A {
function myFunction() public pure returns (string memory) {
return "Function from C";
}
}
contract D is B, C {
// কোন `myFunction` ফাংশনটি ব্যবহার করা হবে?
}এখানে, কন্ট্রাক্ট D B এবং C থেকে ইনহেরিট করেছে, এবং উভয় কন্ট্রাক্টেই myFunction নামে একটি ফাংশন ডিফাইন করা রয়েছে। এ ক্ষেত্রে, Solidity নির্ধারণ করতে পারে না কোন ফাংশনটি ব্যবহার করা হবে।
সমাধান: Solidity তে এই সমস্যা সমাধানের জন্য virtual এবং override কিওয়ার্ড ব্যবহার করা হয়।
4. virtual এবং override কিওয়ার্ড
virtual কিওয়ার্ড ব্যবহার করা হয় ফাংশন বা ভেরিয়েবল ডিফাইন করার সময়, যা নির্দেশ করে যে এই ফাংশন বা ভেরিয়েবলটি ভবিষ্যতে অন্য কন্ট্রাক্ট দ্বারা ওভাররাইড (override) করা যেতে পারে। আর override কিওয়ার্ড ব্যবহার করা হয় যে ফাংশন বা ভেরিয়েবলটি পূর্বের কন্ট্রাক্টের কোনো একটি ফাংশন বা ভেরিয়েবলকে ওভাররাইড করছে।
উদাহরণ:
pragma solidity ^0.8.0;
contract A {
function myFunction() public pure virtual returns (string memory) {
return "Function from A";
}
}
contract B is A {
function myFunction() public pure override returns (string memory) {
return "Function from B";
}
}
contract C is A {
function myFunction() public pure override returns (string memory) {
return "Function from C";
}
}
contract D is B, C {
function myFunction() public pure override returns (string memory) {
return "Function from D";
}
}এখানে, myFunction ফাংশনটি প্রথমে A কন্ট্রাক্টে virtual হিসেবে ডিফাইন করা হয়েছে, এবং পরে B, C, এবং D কন্ট্রাক্টে override করা হয়েছে। D কন্ট্রাক্টে ফাংশনটি শেষ পর্যন্ত override হয়ে নতুন মান প্রদান করবে।
সারাংশ
Multiple Inheritance এবং Contract Inheritance Chain Solidity তে কোড পুনঃব্যবহারযোগ্যতা এবং কোড কাঠামোকে আরও সুষম ও সুসংগঠিত করতে সহায়তা করে। Multiple Inheritance একাধিক কন্ট্রাক্ট থেকে ফাংশন এবং প্রোপার্টি গ্রহণ করতে ব্যবহৃত হয়, এবং Contract Inheritance Chain এর মাধ্যমে একাধিক স্তরের কন্ট্রাক্ট সম্পর্ক তৈরি করা যায়। যদিও diamond problem কিছু সমস্যা সৃষ্টি করতে পারে, তবে virtual এবং override কিওয়ার্ড ব্যবহার করে এই সমস্যার সমাধান করা সম্ভব।
Solidity তে Interfaces এবং Abstract Contracts দুইটি গুরুত্বপূর্ণ কনসেপ্ট যা স্মার্ট কন্ট্রাক্টের মধ্যে ইন্টারঅ্যাকশন, কন্ট্রাক্টের পুনঃব্যবহারযোগ্যতা এবং লজিক বিচ্ছিন্ন করতে সহায়তা করে। এগুলি একাধিক কন্ট্রাক্টের মধ্যে যোগাযোগ, ডিপেনডেন্সি এবং কোডের উন্নত পরিচালনা নিশ্চিত করে।
১. Interfaces
Interface Solidity তে একটি বিশেষ ধরনের কন্ট্রাক্ট যা শুধুমাত্র ফাংশনের সিগনেচার (function signature) ডিফাইন করে, এবং কোনো কন্ট্রাক্টের ইমপ্লিমেন্টেশন বা লজিক প্রদান করে না। এটি সাধারণত একাধিক কন্ট্রাক্টের মধ্যে যোগাযোগ স্থাপন এবং ইন্টারঅ্যাকশন করার জন্য ব্যবহৃত হয়।
- Interface কন্ট্রাক্টে কেবলমাত্র ফাংশনের সিগনেচার থাকতে পারে, এর মধ্যে কোনো কন্ট্রাক্টের বাস্তবায়ন (implementation) থাকে না।
- Interface এর মধ্যে কোনো ডেটা স্টেট বা ভেরিয়েবল থাকতে পারে না।
- Interface কন্ট্রাক্ট অন্য কোনো কন্ট্রাক্টে inherit করা হয় এবং ইমপ্লিমেন্ট করা হয়।
Interface এর উদাহরণ:
pragma solidity ^0.8.0;
interface IToken {
function transfer(address recipient, uint amount) external returns (bool);
function balanceOf(address account) external view returns (uint);
}
contract MyContract {
IToken token;
constructor(address tokenAddress) {
token = IToken(tokenAddress); // Interface এর মাধ্যমে ইন্টারঅ্যাকশন
}
function transferTokens(address recipient, uint amount) public {
token.transfer(recipient, amount); // Interface এর মাধ্যমে transfer ফাংশন কল
}
function getBalance(address account) public view returns (uint) {
return token.balanceOf(account); // Interface এর মাধ্যমে balance চেক
}
}এখানে:
ITokenএকটি interface যা একটি ERC20 টোকেন কন্ট্রাক্টের মতো ফাংশনগুলোর সিগনেচার ডিফাইন করে (যেমনtransferএবংbalanceOf)।MyContractকন্ট্রাক্টেITokeninterface এর মাধ্যমে টোকেন কন্ট্রাক্টের ফাংশনগুলির সাথে ইন্টারঅ্যাক্ট করা হচ্ছে।
Interface এর সুবিধা:
- ইন্টারঅ্যাকশন: একাধিক কন্ট্রাক্টের মধ্যে স্ট্যান্ডার্ড ইন্টারফেসের মাধ্যমে ইন্টারঅ্যাকশন সহজ হয়।
- কোডের পুনঃব্যবহারযোগ্যতা: একবার একটি interface ডিফাইন করার পর, আপনি সেটি বিভিন্ন কন্ট্রাক্টে পুনরায় ব্যবহার করতে পারেন।
- কন্ট্রাক্টের বিচ্ছিন্নতা: ইন্টারফেস কন্ট্রাক্টের লজিক এবং ডেটার চেয়ে শুধুমাত্র ফাংশনের সিগনেচার প্রদান করে, যার ফলে উন্নত বিচ্ছিন্নতা এবং নিরাপত্তা নিশ্চিত করা যায়।
২. Abstract Contracts
Abstract contracts হল এমন কন্ট্রাক্ট যা সম্পূর্ণভাবে কাজ করতে সক্ষম না এবং এদের মধ্যে কিছু ফাংশন ডিফাইন করা থাকে কিন্তু পূর্ণভাবে ইমপ্লিমেন্ট করা থাকে না। Abstract contract গুলি সাধারণত একটি বেস কন্ট্রাক্ট হিসেবে কাজ করে, যার মধ্য দিয়ে অন্য কন্ট্রাক্টগুলিতে সাধারণ লজিক ডিফাইন করা যায়।
- Abstract contract এর মধ্যে কিছু বা সমস্ত ফাংশন
abstractহতে পারে, যার মানে এই ফাংশনগুলো শুধু সিগনেচার ডিফাইন করে এবং ইমপ্লিমেন্টেশন উপস্থাপন করে না। - Abstract contract এর মাধ্যমে আপনি কন্ট্রাক্টের পুনঃব্যবহারযোগ্য লজিক তৈরি করতে পারেন এবং অন্যান্য কন্ট্রাক্টে এর ইমপ্লিমেন্টেশন বা ব্যবহার করতে পারেন।
Abstract Contract এর উদাহরণ:
pragma solidity ^0.8.0;
abstract contract Animal {
string public name;
// abstract function
function sound() public virtual returns (string memory);
}
contract Dog is Animal {
constructor(string memory _name) {
name = _name;
}
// Implementing the abstract function
function sound() public override returns (string memory) {
return "Bark";
}
}
contract Cat is Animal {
constructor(string memory _name) {
name = _name;
}
// Implementing the abstract function
function sound() public override returns (string memory) {
return "Meow";
}
}এখানে:
Animalএকটি abstract contract, যাsoundনামক একটিabstractফাংশন ডিফাইন করেছে।DogএবংCatকন্ট্রাক্টগুলোAnimalabstract contract থেকে ইনহেরিট করে এবংsoundফাংশনের ইমপ্লিমেন্টেশন প্রদান করেছে।
Abstract Contract এর সুবিধা:
- কোডের পুনঃব্যবহারযোগ্যতা: Abstract contracts ব্যবহার করে সাধারণ লজিক ডিফাইন করা যায় যা বিভিন্ন কন্ট্রাক্টে ব্যবহার করা যায়।
- বিকল্প ইমপ্লিমেন্টেশন: Abstract contract ব্যবহার করে আপনি শুধুমাত্র ফাংশনের সিগনেচার ডিফাইন করতে পারেন এবং পরে নির্দিষ্ট কন্ট্রাক্টে তাদের ইমপ্লিমেন্টেশন প্রদান করতে পারেন।
- বেস কন্ট্রাক্ট: Abstract contract এক ধরনের বেস কন্ট্রাক্ট হিসেবে কাজ করে, যেটি অন্যান্য কন্ট্রাক্টগুলোর মধ্যে সাধারণ বৈশিষ্ট্য এবং ফাংশন সরবরাহ করে।
Interfaces এবং Abstract Contracts এর মধ্যে পার্থক্য
| বৈশিষ্ট্য | Interface | Abstract Contract |
|---|---|---|
| ফাংশনের সিগনেচার | শুধুমাত্র সিগনেচার ডিফাইন করা হয় | সিগনেচার ও ইমপ্লিমেন্টেশন হতে পারে |
| স্টেট ভেরিয়েবল | স্টেট ভেরিয়েবল থাকতে পারে না | স্টেট ভেরিয়েবল থাকতে পারে |
| ইনহেরিট করা | Interface কে শুধুমাত্র ইনহেরিট করা যায় | Abstract contract ইনহেরিট করা যায় এবং ফাংশন ইমপ্লিমেন্ট করা হয় |
| অ্যাবস্ট্রাক্ট ফাংশন | ইন্টারফেসে ফাংশন ডিফাইন করা হয় | অ্যাবস্ট্রাক্ট ফাংশন থাকতে পারে |
| ব্রেকথ্রু লজিক | ইমপ্লিমেন্টেশন প্রদান করে না | কিছু লজিক ইমপ্লিমেন্ট করা হয় |
সারাংশ
Interfaces এবং Abstract Contracts Solidity তে দুটি গুরুত্বপূর্ণ কনসেপ্ট যা কন্ট্রাক্টের মধ্যে পুনঃব্যবহারযোগ্যতা, বিচ্ছিন্নতা, এবং নিরাপত্তা নিশ্চিত করতে ব্যবহৃত হয়। Interface কন্ট্রাক্টে শুধুমাত্র ফাংশনের সিগনেচার ডিফাইন করা হয়, এবং এটি একাধিক কন্ট্রাক্টের মধ্যে যোগাযোগ স্থাপন করতে ব্যবহৃত হয়, যখন Abstract Contracts কিছু ফাংশনের সিগনেচার এবং তাদের ইমপ্লিমেন্টেশন ডিফাইন করে, যেটি অন্যান্য কন্ট্রাক্টের বেস হিসেবে কাজ করে। এই দুটি কনসেপ্ট কন্ট্রাক্টের মধ্যে ইন্টারঅ্যাকশন এবং কোড পুনঃব্যবহার সহজতর করে।
Interfaces Solidity তে একটি গুরুত্বপূর্ণ ফিচার, যা বিভিন্ন কন্ট্রাক্টের মধ্যে যোগাযোগ (communication) এবং ইন্টারঅ্যাকশন সহজ করে তোলে। যখন বিভিন্ন কন্ট্রাক্ট একে অপরের সাথে ইন্টারঅ্যাক্ট করতে চায়, তখন interface ব্যবহার করা হয়। Interface হলো একটি কন্ট্রাক্টের ফাংশন সিগনেচার যা কেবলমাত্র ফাংশনগুলির স্বাক্ষর (signature) প্রদান করে, কিন্তু তাদের বাস্তবায়ন বা কোড প্রদান করে না।
Interfaces এর মাধ্যমে এক কন্ট্রাক্ট অন্য কন্ট্রাক্টের ফাংশন কল করতে পারে, কিন্তু কন্ট্রাক্টের বাস্তবায়ন (implementation) সম্পর্কে কোনো ধারণা না থাকলেও কেবলমাত্র সেই কন্ট্রাক্টের ফাংশন সিগনেচার জানা প্রয়োজন।
Interface এর বৈশিষ্ট্য:
- শুধুমাত্র ফাংশন সিগনেচার: Interface একটি কন্ট্রাক্টের ফাংশনগুলো ঘোষণার জন্য ব্যবহৃত হয়, তবে এর বাস্তবায়ন অন্তর্ভুক্ত হয় না।
- কোনো ভেরিয়েবল বা স্টোরেজ নেই: Interface তে কোনো স্টোরেজ ভেরিয়েবল থাকে না, শুধুমাত্র ফাংশন সিগনেচার থাকে।
- Multiple Inheritance: Solidity তে একাধিক Interface উত্তরাধিকারসূত্রে নেওয়া যেতে পারে (multiple inheritance)।
- বস্তুনিষ্ঠতা: Interface একটি কন্ট্রাক্টের বাইরে অন্য কন্ট্রাক্টের সাথে যোগাযোগের একটি নির্দিষ্ট মানদণ্ড (standard) তৈরি করে।
Interface ব্যবহার করার জন্য Steps
- Interface Declaration
- Interface Implementation
- Contract Communication
১. Interface Declaration
Interface ডিক্লেয়ার করার সময়, শুধুমাত্র ফাংশন সিগনেচার দেওয়া হয় এবং তার বাস্তবায়ন বা কোড দেওয়া হয় না।
pragma solidity ^0.8.0;
// Interface Declaration
interface IToken {
function transfer(address recipient, uint amount) external returns (bool);
function balanceOf(address account) external view returns (uint);
}এখানে:
ITokenএকটি interface যা দুটি ফাংশন ঘোষণা করেছে:transfer: টোকেন ট্রান্সফারের জন্য ব্যবহৃত হবে।balanceOf: নির্দিষ্ট অ্যাকাউন্টের ব্যালেন্স ফেরত দেয়।
২. Interface Implementation
এখন আপনি একটি কন্ট্রাক্ট তৈরি করতে পারেন যা এই Interface-এর বাস্তবায়ন করবে। এখানে, MyToken কন্ট্রাক্টটি IToken ইন্টারফেসের বাস্তবায়ন করবে।
pragma solidity ^0.8.0;
// Interface Declaration
interface IToken {
function transfer(address recipient, uint amount) external returns (bool);
function balanceOf(address account) external view returns (uint);
}
// Contract Implementation
contract MyToken is IToken {
mapping(address => uint) public balances;
// Implementing the transfer function from IToken interface
function transfer(address recipient, uint amount) public override returns (bool) {
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount;
balances[recipient] += amount;
return true;
}
// Implementing the balanceOf function from IToken interface
function balanceOf(address account) public view override returns (uint) {
return balances[account];
}
// Function to mint tokens
function mint(address account, uint amount) public {
balances[account] += amount;
}
}এখানে:
MyTokenকন্ট্রাক্টেITokenইন্টারফেসের দুটি ফাংশনের বাস্তবায়ন রয়েছে:transfer: একটি নির্দিষ্ট পরিমাণ টোকেন প্রেরণ করে।balanceOf: কোনো অ্যাকাউন্টের ব্যালেন্স ফেরত দেয়।
এবং mint ফাংশনটি MyToken কন্ট্রাক্টের জন্য তৈরি করা হয়েছে, যা নতুন টোকেন তৈরি করে (এই ফাংশনটি IToken ইন্টারফেসের অংশ নয়)।
৩. Contract Communication
এখন, আমরা অন্য একটি কন্ট্রাক্ট থেকে MyToken কন্ট্রাক্টের ফাংশন কল করতে চাই, এটি করতে IToken ইন্টারফেস ব্যবহার করা যেতে পারে।
pragma solidity ^0.8.0;
contract TokenSender {
IToken public tokenContract;
// Constructor to set the token contract address
constructor(address _tokenAddress) {
tokenContract = IToken(_tokenAddress);
}
// Function to send tokens using the IToken interface
function sendTokens(address recipient, uint amount) public returns (bool) {
return tokenContract.transfer(recipient, amount);
}
}এখানে:
TokenSenderকন্ট্রাক্টেITokenইন্টারফেস ব্যবহার করা হয়েছে যাMyTokenকন্ট্রাক্টের সাথে যোগাযোগ করতে সক্ষম।sendTokensফাংশনটিITokenইন্টারফেসেরtransferফাংশন কল করে, যাMyTokenকন্ট্রাক্টের মাধ্যমে টোকেন প্রেরণ করে।
Solidity তে Interface এর সুবিধা
- আন্তঃকন্ট্রাক্ট কমিউনিকেশন: Interfaces কন্ট্রাক্টগুলোর মধ্যে যোগাযোগ সহজ করে তোলে, যাতে তারা একে অপরের ফাংশনগুলি কল করতে পারে।
- ডেটা আর্কিটেকচার উন্নতি: কন্ট্রাক্টগুলোর মধ্যে স্পষ্ট ইন্টারফেসের মাধ্যমে ডেটার নিরাপত্তা এবং সঠিক ব্যবস্থাপনা নিশ্চিত করা যায়।
- স্ট্যান্ডার্ডাইজেশন: বিশেষ করে ERC-20, ERC-721, ERC-1155 ইত্যাদি স্ট্যান্ডার্ড প্রোটোকলগুলিতে ইন্টারফেস ব্যবহৃত হয়। এসব প্রোটোকলে বিভিন্ন কন্ট্রাক্টের মধ্যে সঙ্গতি বজায় রাখা সহজ হয়।
- কোডের রিইউজযোগ্যতা: একবার ইন্টারফেস ডিফাইন করে, আপনি একাধিক কন্ট্রাক্টে সেটি ব্যবহার করতে পারেন, যা কোডের পুনঃব্যবহারযোগ্যতা নিশ্চিত করে।
সারাংশ
Interfaces Solidity তে বিভিন্ন কন্ট্রাক্টের মধ্যে ইন্টারঅ্যাকশন এবং যোগাযোগ সহজ করতে ব্যবহৃত হয়। এটি কেবলমাত্র কন্ট্রাক্টের ফাংশন সিগনেচার প্রদান করে, বাস্তবায়ন নয়। একটি কন্ট্রাক্ট যে ইন্টারফেস অনুসরণ করবে, সে কেবল সেই ইন্টারফেসের ঘোষিত ফাংশনগুলির বাস্তবায়ন করবে। এতে কন্ট্রাক্টগুলোর মধ্যে স্ট্যান্ডার্ডাইজেশন, নিরাপত্তা এবং যোগাযোগ সহজ হয়। Interfaces ব্যবহারের মাধ্যমে একটি কন্ট্রাক্ট অন্য কন্ট্রাক্টের কার্যকারিতা ব্যবহার করতে পারে, যা স্মার্ট কন্ট্রাক্ট ডেভেলপমেন্টে অনেক সুবিধা প্রদান করে।
Read more