سازنده در سالیدیتی Solidity Constructors
Solidity Constructors یا سازنده در سالیدیتی چیست؟
تو زبانهای برنامهنویسی شیگرا (object-oriented programming)، استفاده از Constructor روشی خاص برای فراخوانی یا مقداردهی اولیه به متغیرهاست. حالا توی زبان برنامهنویسی سالیدیتی، عملکرد constructor به این ترتیب هستش که constructorای که درون قرارداد هوشمند نوشته میشه، فقط و فقط یک بار فراخوانی و اجرا میشه. خب حالا با توجه به اینکه گفتیم constructor فقط یکبار اجرا میشه، اون یکبار کی خواهد بود؟ بله، اگه درست حدس زده باشین، زمان اجرا شدن constructor وقتی هستش که قرارداد هوشمند ما داره روی شبکه بلاکچین دیپلوی میشه.
پس متوجه میشیم که constructor توی قراردادهای هوشمند سالیدیتی (solidity constructors) برای مقداردهی اولیه وضعیت قرارداد هوشمندمون استفاده میشه. ضمناً اگر که توی قرارداد هوشمند، constructor تعریف نشده باشه، کامپایلر سالیدیتی بهطور خودکار یک constructor پیشفرض ایجاد میکنه. تا اینجای، سعی کردیم مفهوم کلی constructor رو توی سالیدیتی بیان کنیم، در ادامه ی آموزشمون با توکن خان همراه باشید تا اطلاعات بیشتری از این مفهوم رو باهاتون در میان بگذاریم.
قبل از مطالعه کامل مقاله “سازنده در سالیدیتی Solidity Constructors” پیشنهاد میکنیم مقالات دیگر حوزه آموزش زبان سالیدیتی را هم مطالعه کنید.
عملگرها در برنامه نویسی سالیدیتی
آرایه ها (Array) در زبان برنامه نویسی Solidity
Struct در قراردادهای هوشمند سالیدیتی Solidity
Interface در قراردادهای هوشمند Solidity
وراثت در سالیدیتی Solidity Inheritance
مدیریت خطا در سالیدیتی Error Handling
Mapping در قرارداد هوشمند Solidity
ایجاد constructor در سالیدیتی
در واقع constructor نوعی تابع هستش که در زمانی که نیاز به مقداردهی اولیه به یک شی در قرارداد هوشمندمون وجود داشته باشه، مورد استفاده قرار میگیره. همونطور که پیشتر هم عنوان کردیم، این تابع یا همون سازنده در سالیدیتی در زمان ایجاد قرارداد هوشمند تنها یک بار فراخوانی میشه و ازش برای تنظیم مقادیر اولیه توی کدهای سالیدیتی استفاده میشه. دقت داشته باشین که هر قرارداد میتونه فقط یه constructor داشته باشه که پس از یک بار فراخوانی و اجرا بار دیگهای اجرا نمیشه.
تابع constructor از طریق نوشتن کلمه کلیدی constructor()و بدون هر گونه نام تابعی تعریف میشه. توجه داشته باشید که نیازی به اضافه کردن کلمه کلیدی تابع نیست، چون constructor یک ویژگی خاص در سالیدیتی هستش و نیازی نیست که بخوایم بهصورت جداگونه به عنوان تابع تعریفش کنیم. البته توجه داشته باشین که Constructor در قراردادهای هوشمند سالیدیتی یک تابع کاملا اختیاری هستش که متغیرهای سراسری یا همون state variable های قرارداد رو مقداردهی اولیه میکنه.
Constructor ها سابقاً در نسخه 0.5.0 کامپایلر سالیدیتی، میتونستن هم بهصورت public و هم بهصورت internal ایجاد بشن، اما دیگه از نسخه کامپایلر مربوطه به بعد، دیگه در حال حاضر هیچ access modifier ای توی تعریفشون قرار نمیگیره. (پیشنهاد میکنم این مطلب رو هم بخونین: access modifier ها در سالیدیتی)
همونطور که گفتیم constructor یک تابع ویژه است که تنها یک بار و اون هم در زمان دیپلوی شدن قرارداد هوشمند فراخوانی و اجرا میشه و بعدش دیگه به هیچ طریقی نمیشه فراخوانیش کرد.
این خصوصیت برای تنظیم مواردی خاص در زمان دیپلوی کردن و اجرای قرارداد هوشمند دارای اهمیت زیادی میتونه باشه. به عنوان نمونه با مشخص کردن اینکه چه کسی قرارداد هوشمند رو ایجاد کرده، اجازه نابود کردن یا همون destruct کردن قرارداد هوشمند رو تنها به اون شخص داده بشه. حالا این ویژگی در این خصوص چه کارهایی میتونه انجام بده؟
- آدرس مالک به عنوان آدرسی که قرارداد هوشمند را ایجاد و دیپلوی کرده است در constructor قرار داده میشه.
- به محض تخریب یا نابودی قرارداد، constructor این موضوع رو بررسی میکنه که چه کسی تابع رو فراخوانی کرده.
- در صورتی که constructor توسط مالک فراخوانده شده باشه، قرارداد هوشمند از بین میره.
- در صورتی که این کار توسط مالک انجام نشده باشه، خطا ایجاد میشه.
چه زمانی از constructor در سالیدیتی استفاده می کنیم؟
وقتی قصد داشته باشیم یک قرارداد هوشمند رو در بلاک چین ایجاد و دیپلوی کنیم، نیاز داریم تا برای تنظیم و مقداردهی اولیه state variableهامون از constructor بهره ببریم. به عنوان نمونه، یک سری از مواردی که میتونیم در زمان ایجاد قرارداد هوشمند به کمک constructor تنظیم و مشخص کنیم به ترتیب زیر هستن:
- مالک قرارداد: میتونیم آدرسی رو به عنوان آدرس مالک یا همون کسی که قرارداد هوشمند رو ایجاد کرده مشخص کنیم.
- حداکثر مقدار: میتونیم سقفی برای حداکثر تعداد یک توکن در نظر بگیریم و اون رو توسط Constructor در کد سالیدیتیمون تنظیم کنیم.
- میتونیم مقادیر درست یا اشتباه رو مشخص کنیم.
- میتونیم هر پارامتری که قصد ذخیرهسازی توی قرارداد داریم رو از همون اول مشخص کنیم.
- و کلی موارد دیگه.
اگر در کنار تعریف constructor در سالیدیتی، تابع دیگهای رو برای تغییر دادن state variableهای قرارداد تعریف و اجرا نکنیم، تابع constructor تا زمانی که بلاک چین کار میکنه، بدون تغییر باقی میمونه! در نتیجه میشه اینطور گفت که استفاده از اون برای مواردی که نمیخوایم تغییری تو قرارداد هوشمند ایجاد کنیم یا اینکه کلاً نیازی به تغییر state variableهای قرارداد وجود نداره، بسیار مناسب هستش.
ویژگیهای کلی یک constructor در سالیدیتی
همونطور که تا اینجای آموزش صحبت کردیم، فهمیدیم که constructor ها در سالیدیتی یک سری ویژگی هایی دارن. حالا تو این قسمت، به نظرم بهتره یک جمعبندی از ویژگی اونها رو بهصورت خلاصه عنوان کنیم:
- برای هر قرارداد هوشمند میتوان تنها یک تابع constructor تعریف کرد.
- هدف از تعریف constructor در سالیدیتی مقداردهی اولیه به state variableها قبل از deploy شدن هستش.
- تابع constructor یک نوع تابع اختیاریه و بنابراین، استفاده از اون در قرارداد هوشمند هم کاملاً اختیاری هستش.
- اگر تابع constructor توی سالیدیتی تعریف نشه، تابعی با عنوان default constructor در قرارداد هوشمند وجود داره که جایگزین اون خواهد شد.
- constructor در سالیدیتی تنها یک بار فراخوانی و اجرا میشه و بعد از اون دیگه به هیچ طریقی دوباره فراخوانی و اجرا نخواهد شد. والسلام!
- Constructor هیچگونه access modifier ای نمیگیرد.
نحوه ارث بری از constructor یک قرارداد هوشمند
همونطور که تو ویژگیهای constructor عنوان کردیم، در صورتی که این تابع رو توی قرارداد هوشمند تعریف نکرده باشیم، یک constructor پیشفرض فراخوانی میشه. حالا در صورتی که constructor در یک قرارداد والد(base contract) تعریف شده باشه و آرگومانهایی هم داشته باشه، قرارداد فرزند(derived contract) هم باید پارامترهای مورد نیاز را در اختیار constructor پدر قرار بده. (برای یادآوری بهتره عرض کنم که آرگومانها یا همان arguments به مقادیر و یا پارامترهای حقیقی گفته میشه که با فراخوانی برنامه به یک تابع یا زیر تابع وارد میشه.)
حالا در صورتی که قرارداد فرزند هیچ پارامتری رو در اختیار constructor والدش قرار نده، قرارداد فرزند به یک قرارداد انتزاعی یا همون Abstract Contract تبدیل خواهد شد. مفهوم انتزاعی در مقابل مفهوم واقعی (Concrete) به کار میره و در واقع یک طرح یا الگوی کلی ای هستش برای چیزهای عینی که در دنیای واقعی و با چشم میبینیم. در برنامهنویسی شیگرا به کلاسهایی که قابل نمونهسازی باشند کلاسهای واقعی و به اونهایی که قابل نمونهسازی نباشند کلاسهای انتزاعی گفته میشه.
برای فراخوانی یا همون call کردن constructor قرارداد والد سه روش داریم که در زیر عنوانشون کردیم:
- مقداردهی اولیه مستقیم
- مقداردهی اولیه غیرمستقیم
- ترکیبی از مقداردهی اولیه مستقیم و غیرمستقیم
مقداردهی به constructor های زبان برنامه نویسی سالیدیتی در زمان ارث بری
نمونه کد مقداردهی اولیه مستقیم
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
// SPDX-License-Identifier: TokenKhan // یک کد سالیدیتی برای نمایش عملکرد // مقداردهی اولیه مستقیم به تابع سازنده در زمان ارث بری // Constructor in Inheritance pragma solidity ^0.8.0; // ساخت کانترکت والد contract Base { // تعریف متغیر عددی uint number; // constructor تعریف constructor(uint _number) { number = _number; } // تعریف تابع function Print() public pure returns (string memory) { return "Direct Initialization"; } } // کانترکت فرزند، در حال ارث بری از کانترکت والد // Child contract --> 'Derived' // parent contract --> 'Base' contract Derived is Base(2) { // تعریف یک تابع برای دسترسی به // متغیرهای کانترکت والد function getNumber() external view returns (uint) { uint result = number ** 2; return result; } } // کانترکت فراخوانی کننده contract caller { // ساخت یک شئ از کانترکت فرزند Derived obj = new Derived(); // دسترسی به توابع کانترکت والد و فرزند // با استفاده از شئ ای از قرارداد فرزند function getResult() public view returns (uint) { return obj.getNumber(); } } |
لینک دانلود : دریافت فایل سالیدیتی مقداردهی اولیه مستقیم
نمونه کد مقداردهی اولیه غیر مستقیم
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
// SPDX-License-Identifier: TokenKhan // یک کد سالیدیتی برای نمایش عملکرد // مقداردهی اولیه غیر مستقیم به تابع سازنده در زمان ارث بری // Constructor in Inheritance pragma solidity ^0.8.0; // ساخت کانترکت والد contract Base { // State Variable تعریف یک string str; // constructor تعریف constructor(string memory _str) { str = _str; } // تعریف یک تابع function Print() public pure returns(string memory) { return "Indirect Initialization"; } } // کانترکت فرزند، در حال ارث بری از کانترکت والد // Child contract --> 'Derived' // parent contract --> 'Base' contract Derived is Base { // constructor تعریف constructor(string memory _info) Base(string(abi.encodePacked(_info, _info))) {} // تعریف یک تابع // 'str' برگرداندن مقدار // از کانترکت والد function getStr() public view returns(string memory) { return str; } } // اسمارت کانترکت فراخوانی کننده contract caller { // ایجاد یک آبجکت از // کانترکت فرزند Derived obj = new Derived("TokenKhan"); // تعریف یک تابع به منظور دسترسی به // توابع کانترکت والد و فرزند function getResult() public view { obj.Print(); obj.getStr(); } } |
لینک دانلود : دریافت فایل سالیدیتی مقداردهی اولیه غیر مستقیم
اهمیت وجود Constructor در قراردادهای هوشمند سالیدیتی
تعریف یک تابع constructor در قرارداد هوشمند کارکردها و فواید زیادی میتونه برامون داشته باشه، با استفاده از constructor میشه مقدار یک state variable رو در زمان دیپلوی تعریف کرد و همینطور، میشه فراخوانی تابع خاصی رو مثلاً به یک زمان خاص محدود کرد، و یا کاربردهای دیگه ای که میتونیم با استفاده از اون توی قرارداد هوشمندمون پیادهسازیش کنیم.
سخن آخر
در هنگام ایجاد یک قرارداد هوشمند با زبان برنامهنویسی سالیدیتی (Solidity)، میتوانیم تابعی با نام سازنده یا constructor در سالیدیتی تعریف کنیم. این تابع خاص که با نام constructor از آن یاد میکنیم شامل منطق اولیهسازی state variableهای اسمارت کانترکت ما است. در زبانهای برنامهنویسی شیگرا (OOP) در زمانی که یک شی (Object) از یک کلاس (Class) نمونهسازی شود، یک سازنده یا constructor فراخوانی میشه.
constructor فقط و فقط یکبار، و آن هم زمانی فراخوانده میشه که قرارداد هوشمند میخواد دیپلوی بشه. پس از این دیگه هیچ راهی برای دوباره فراخوانده شدن constructor وجود نداره. این تابع این امکان رو برای برنامهنویس فراهم میکنه تا در صورت نیاز و بنا بر خواست خودش، چگونگی ایجاد شی جدید رو هم مدیریت بکنه و یا اینکه اون رو در همون زمان ساخت و دیپلوی کردن توی بلاکچین، شخصیسازی کنه. در نتیجه استفاده از constructor توی سالیدیتی و قرارداد هوشمند کاملا اختیاری هستش و اگر که constructor توی کد ما تعریف نشه، کامپایلر یک default constructor برامون ایجاد میکنه و همون رو اجرا میکنه.
منابع معتبر مرتبط:
https://www.geeksforgeeks.org/solidity-constructors
https://medium.com/coinmonks/solidity-tutorial-all-about-constructors
مطالب زیر را حتما مطالعه کنید
بررسی رفتار توابع View و Pure در سالیدیتی Solidity
توابع Payable در قراردادهای هوشمند Solidity
سالیدیتی Solidity چیست؟
سطح دسترسی Visibility در سالیدیتی Solidity
توابع Function در سالیدیتی Solidity
انواع حافظه در قرارداد هوشمند سالیدیتی
8 دیدگاه
به گفتگوی ما بپیوندید و دیدگاه خود را با ما در میان بگذارید.
مطلب خوبی بود همکار گرامی
مطلبتون بسیار مفید بود
چه مطلب خوبی
ایا مشاوره هم دارین برای سالیدیتی؟ قیمت مشاورتون چقدره؟
مقالاتتون عالین واقعا!
احسنت عالی بود
خیلی ممنون از توضیحات خوبتون
بسیار گویا و شفاف بیان کردید