رابط(Interface) در قراردادهای هوشمند Solidity
یک رابط (Interface) در Solidity مشابه قراردادهای Interface در زبان های برنامه نویسی شی گرا سنتی عمل می کند. در برنامه نویسی شی گرا، یک Interface توصیفی از تمام عملکردهایی است که یک شی باید داشته باشد تا بتواند کار کند. هدف یک Interface اعمال مجموعه ای از ویژگی های تعریف شده و اجرای توابع خاص در یک شی دیگر است. به عنوان مثال، هنگامی که یک سوئیچ چراغ را باز می کنید، چراغ روشن می شود. برای شما مهم نیست که چگونه چراغ روشن می شود.
رابط(Interface) در Solidity چیست؟
Interface ها اغلب در بالای قرارداد هوشمند یافت می شوند. آنها با استفاده از کلمه کلیدی “Interface” شناسایی می شوند. Interface شامل امضاهای تابع بدون اجرای تعریف تابع است (جزئیات پیاده سازی اهمیت کمتری دارند). می توانید از یک Interface در قرارداد خود برای فراخوانی توابع در قرارداد دیگر استفاده کنید.
مثال زیر نمونه قرارداد هوشمند با رابط IERC20 را نشان می دهد. امضاهای تابع این رابط در قالب لیست هستند و با نقطه ویرگول به پایان می رسند. Interface نیازی به بدنه (جزئیات پیاده سازی) هر تابع ندارد. افزودن این رابط، توابع IERC20 را برای استفاده در قرارداد نمونه در دسترس قرار می دهد.
//import the IERC20 interface
//the IERC20 interface lists functions available but no definitions
//as an example you do not know what totalSupply, balanceOf and transfer do
//because there is no function definition or function implementation listed
//you do know that the functions are available to use
pragma solidity ^0.8.7;
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 allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient,uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
contract sampleContract{
// do something
// do something
}
رابط ها در سناریوهایی که برنامه شما نیاز به توسعه پذیری دارد اما نمی خواهید پیچیدگی بیشتری ایجاد کنید بسیار مفید هستند. آنها تکرار کد و سربار را کاهش می دهند.
ویژگی های رابط(Interface)
- با کلمه کلیدی “interface” یک رابط ایجاد می شود.
- برخی از نام های Interface با یک “I” شروع می شوند تا شناسایی آنها در کد آسان تر شود.
- تمام توابع Interface به طور ضمنی مجازی هستند.
- می توانید یک تابع Interface را لغو کنید.
- قراردادها می توانند Interface ها را به ارث ببرند همانطور که قراردادهای دیگر را به ارث می برند.
- Interface ها می توانند از Interface های دیگر ارث ببرند که همان قوانین وراثت عادی است.
- همه توابعی که از Interface به ارث میبرند باید override modifier را روی هر تابعی که یک تابع Interface را overrides میکند تنظیم کنند. در غیر این صورت کامپایلر یک خطا ایجاد می کند.
- انواع داده های تعریف شده در داخل Interface ها را می توان از قراردادهای دیگر دسترسی داشت. برای مثال، قراردادی که از Interface نمونه زیر استفاده میکند، میتواند به Iauto.carType و Iauto.vehicle دسترسی داشته باشد.
pragma solidity ^0.8.7;
interface Iauto {
enum carType { gas, electric}
struct vehicle { string car; string truck; }
function transfer(address recipient, uint amount) external;
}
محدودیت های رابط(Interface)
- آنها نمی توانند از قراردادهای دیگر ارث ببرند، اما می توانند از Interface های دیگر ارث ببرند.
- توابع یک Interface فقط می توانند از نوع external باشند.
- آنها نمی توانند سازنده (Constructor) را اعلام کنند.
- آنها نمی توانند متغیرهای حالت (State Variable) را اعلام کنند.
نحوه ایجاد یک رابط در Solidity
در این مثال می خواهیم یک Interface ایجاد کنیم:
- قرارداد اول حاوی توابعی است که داده ها را برمی گرداند.
- قرارداد دوم با Interface های قرارداد اول
- قرارداد دوم با استفاده از Interface به تمام عملکردهای قرارداد اول دسترسی خواهد داشت.
ابتدا قرارداد زیر را در ریمیکس کپی و اجرا کنید. این قرارداد به نام dataContract شامل چندین تابع است که داده های نمونه را برمی گرداند.
pragma solidity ^0.8.6;
contract dataContract {
function getAge() external pure returns(uint) {
return 25;
}
function getHeight() external pure returns(uint) {
return 6;
}
function getName() external pure returns(string memory) {
return 'Bob';
}
function getCar() external pure returns(string memory) {
return 'truck';
}
}
سپس قرارداد زیر را در ریمیکس کپی و مستقر کنید. این قرارداد حاوی یک رابط برای قرارداد فوق است. آدرس قرارداد بالا را در متغیر حالت در قرارداد زیر قرار دهید.
pragma solidity ^0.8.6;
//defined interface with functions that do not contain an implementation
//declared as type external
interface IDataContractInterface {
function getAge() external pure returns(uint);
function getHeight() external pure returns(uint);
function getName() external pure returns(string memory);
function getCar() external pure returns(string memory);
}
contract MainContract {
// state variable called DataContractAddress that represents the address of the data contract
address private constant DataContractAddress = PASTEFIRSTCONTRACTADDRESSHERE;
// to access the functions in the data contract
// use the interface declared above and wrap the data contract address in ()
// example interfaceName(address).functionName
function getAge() external pure returns(uint) {
return IDataContractInterface(DataContractAddress).getAge();
}
function getHeight() external pure returns(uint) {
return IDataContractInterface(DataContractAddress).getHeight();
}
function getName() external pure returns(string memory) {
return IDataContractInterface(DataContractAddress).getName();
}
function getCar() external pure returns(string memory) {
return IDataContractInterface(DataContractAddress).getCar();
}
}
در نهایت، پس از استقرار قرارداد بالا، هر یک از توابع را اجرا کنید. توابع از Interface برای برقراری ارتباط با اولین قرارداد برای به دست آوردن مقادیر داده استفاده می کنند.
تفاوت بین یک Interface و یک abstract contracts
Interface ها و abstract contracts از بسیاری جهات مشابه هستند. Interface نسبت به abstract contracts بیشتر انتزاعی هستند. همه توابع Interface فاقد پیاده سازی هستند و در abstract contracts حداقل یک تابع فاقد پیاده سازی است. در نتیجه شما نمی توانید یک Interface یا یک abstract contracts را به دلیل عدم اجرای آن کامپایل کنید.
Abstract Contracts:
- به القای الگوهای کدنویسی در برنامه خود کمک کنید.
- ساختار برنامه خود را تعریف و مستند کنید.
- انواع دیگر قراردادها می توانند از abstract contracts ارث ببرند.
- برعکس، در یک قرارداد هوشمند از Interface ها به عنوان نمایش استفاده می شود.
تفاوت بین Interfaces و Libraries
Interfaceها و Libraryها از این جهت مشابه هستند که یک قرارداد انتزاعی را برای ارتقاء پذیری ارائه میکنند که میتواند به روشهای مختلف برای ارتقای قرارداد هوشمند Solidity استفاده شود. با این حال آنها متفاوت هستند و موارد استفاده متفاوت را حل می کنند.
رابط ها:
- نمی تواند شامل منطق فقط تعریف رابط باشد
- عمدتاً به عنوان imports برای تعامل با سایر قراردادها مفید است
- رابط ها برای استقرار/وارد کردن کوچکتر هستند
کتابخانه ها:
- حاوی منطق هستند
- برای اهداف نگهداری و استفاده مجدد، کد را از قرارداد خارج می کنند.
- یک بار دپلوی شده و سپس در قراردادها استفاده می شود.
- Bytecode به طور جداگانه مستقر می شود و بخشی از قراردادهایی نیست که به آنها ارجاع می دهد.
در صورتی که تجربه خاصی در خصوص برنامهنویسی ندارید میتوانید از دورههای رایگان سایت ما “فرازمان“، استفاده کنید. همچنین اگر به دورههای پیشرفتهتری در این خصوص نیاز داشته باشید، ما با آموزش های حرفه ای که در سایتمان قرار دادیم می توانید به سطح دلخواهتان با تلاش و پشتکار برسید.
نقشه راه
راهنما آکادمی فرازمان
برای یادگیری برنامه نویسی بلاکچین…
در این باره بیشتر بخوانید
دیدگاهتان را بنویسید