وراثت در سالیدیتی Solidity Inheritance
وراثت در سالیدیتی Solidity Inheritance چیست؟
وراثت inheritance در سالیدیتی یا همان Solidity Inheritance یک ویژگی مهم و کاربردی در زبانهای برنامهنویسی شیگرا است که موجب افزایش دامنه عملکرد یک برنامه یا قرارداد میشود. در واقع زبان برنامهنویسی سالیدیتی از وراثت در میان قراردادهای هوشمند پشتیبانی میکند به این معنی که میتوان تعداد زیادی قرارداد را در یک قرارداد پایه به ارث برد. بر این اساس به قراردادی که چندین قرارداد میتوانند ویژگیهای آن را به ارث ببرند قرارداد پایه یا مبنا (base contract) و سایر قراردادهایی که از قرارداد پایه ویژگیها را به ارث میبرند قرارداد مشتق (derived contract) گفته میشود.
استفاده از این ویژگی زبان برنامهنویسی سالیدیتی مزایای بسیاری دارد که میتوان از میان آنها به امکان چندبار استفاده از کدها و سازماندهی به کدها، جلوگیری از افزونگی کدها و کم کردن پیچیدگی زمان قطعه کد اشاره کرد اما مزیت اصلی وراثت در سالیدیتی افزایش خوانایی کدها در قرارداد هوشمند است. برای آشنایی بیشتر با این مفهوم و کاربرد آن در زبان برنامهنویسی سالیدیتی با این مقاله در توکن خان همراه باشید.
قبل از مطالعه کامل مقاله “وراثت در سالیدیتی Solidity Inheritance” پیشنهاد میکنیم مقالات دیگر حوزه آموزش جامع سالیدیتی را هم مطالعه کنید.
آرایه ها (Array) در زبان برنامه نویسی Solidity
Struct در قراردادهای هوشمند سالیدیتی Solidity
Interface در قراردادهای هوشمند Solidity
مدیریت خطا در سالیدیتی Error Handling
Mapping در قرارداد هوشمند Solidity
کاربردهای برنامه نویسی سالیدیتی
سالیدیتی چیست؟
قراردادهای هوشمند به عنوان برنامههایی هستند که بر روی بلاک چین و بیشتر بلاک چین اتریوم ذخیره و اجرا میشوند تا طرحی ایدهآل را برای برقراری امنیت بین طرفین قرارداد در زمانی که این قرارداد با کد اجرا میشود، ارائه دهند. قراردادهای هوشمند در این زمینه بسیار موفق عمل کرده اند و بسیار ایمن و قابل پیشبینی هستند.
اما کدهای این قراردادها نیازمند برنامهنویسی هستند و سالیدیتی به عنوان ابزاری برای این کار شناخته میشود و در واقع بهترین ابزار برای این کار است. زبان برنامهنویسی سالیدیتی که در سال 2014 معرفی شد، بعدها توسط تیم بنیانگذاران اتریوم توسعه پیدا کرد و امروز یکی از رایجترین زبانهای برنامهنویسی برای نوشتن قراردادهای هوشمند و اجرای آنها در بلاک چین اتریوم است. با این زبان برنامهنویسی شیگرا و بسیار قابل اعتماد دیگر نوشتن قراردادهای هوشمند اتریوم پیچیده نیست.
سالیدیتی از تمام انواع دادههای زبانهای شیگرا پشتیبانی میکند که شامل موارد زیر هستند:
- بولینBoolean: این نوع داده در سالیدیتی برای نشان دادن مواردی کاربرد دارد که نتایج باینری دارند، یک bool دارای دو مقدار ثابت درست true یا نادرست false است که حالت پیشفرض آن false است.
- عدد صحیح Integer: یک عدد صحیح با علامت (signed integer) با کلمه کلیدی int اعلام میشود که مقداری است که برای ذخیره مقادیر مثبت یا منفی در قراردادهای هوشمند کاربرد دارد. یک عدد صحیح بدون علامت (unsigned integer) با کلمه کلیدی uint اعلام میشود و باید حتما غیرمنفی باشد یعنی مقداری بزرگتر یا مساوی صفر.
- رشته String: رشته با گیومههای تکی یا دوتایی نشان داده میشود.
اصلاح کننده Modifier: اصلاح کننده اغلب پیش از اجرای کد قرارداد هوشمند، شرایط منطقی را تأیید میکند. - آرایه Array: سینتکس برنامه solidity مشابه سایر زبانهای OOP است که از آرایههای تک بعدی و چند بعدی پشتیبانی میکند.
معرفی وراثت در سالیدیتی
زبان برنامهنویسی سالیدیتی از وراثت تک و چندگانه پشتیبانی میکند که به طور کلی باعث گسترش عملکرد یک قرارداد میشوند. در وراثت تک یا Single inheritance توابع، اصلاح کنندهها، رویدادها و متغیرها از قراردادهای والد به قرارداد فرزند انتقال مییابند.
در وراثت چندسطحی یا Multi-level inheritance بیشتر از یک رابطه والد – فرزندی در انتقال ویژگیها ایجاد میشود.
سالیدیتی با کپی کردن کد چندشکلی، از وراثت چندگانه پشتیبانی میکند. نکتهای که باید در نظر داشته باشید این است که همه فراخوانیهای تابع مجازی (virtual) هستند. این ویژگی به معنی این است که بیشتر توابع مشتق شده فراخوانی میشوند به جز زمانی که نام قرارداد صراحتا داده شده باشد. در زمانی که یک قرارداد از چندین قرارداد به ارث میرسد، تنها یک قرارداد تکی بر روی بلاک چین ایجاد میشود، سپس کد برای تمام قراردادهای پایه در قرارداد ایجاد شده کپی میشود.
سیستم وراثت عمومی به خصوص در مورد وراثت چندگانه بسیار شبیه به زبان برنامهنویسی پایتون است. پس در صورتی که با این زبان آشنایی دارید کار کردن با وراثت inheritance در سالیدیتی نیز برایتان آسان است.
چه زمانی و چگونه باید از وراثت در قراردادهای هوشمند Solidity استفاده کرد؟
در موارد زیر در قراردادهای هوشمند سالیدیتی باید از وراثت و مزایای آن بهره برد:
- در زمانی که خواستار ایجاد تغییرات در یک قرارداد و انعکاس آن تغییرات و اصلاحات در قراردادهای دیگر باشید.
- به منظور کاهش وابستگی.
- به منظور استفاده مجدد و چندباره از کدهای موجود.
برای ایجاد وراثت در قراردادها و مشتق شدن یک قرارداد از قرارداد دیگر از کلمه کلیدی is استفاده میکنیم.
1 2 3 4 5 6 |
contract baseContract { //parent contract } contract derivedContract is baseContract { //child contract } |
مثال:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
pragma solidity >=0.4.22 <0.6.0; contract parent{ uint internal id; function setValue(uint _value) public{ id = _value; } } contract child is parent{ function getValue() public view returns(uint){ return id; } } |
برای کنترل اینکه آیا کد قرارداد والدین در یک کد فرزند کامپایل میشود یا نه، اول قرارداد والد و سپس قرارداد فرزند را دیپلوی کنید. به این ترتیب متوجه تفاوت خواهید شد. قرارداد والد تنها شامل متد setValue است در حالی که قرارداد فرزند شامل هر دو متد خودش و قرارداد والد است.
ویژگیهای اساسی وراثت در سالیدیتی
- قراردادهای مشتق شده به همه اعضای غیرخصوصی (state variable و توابع داخلی) دسترسی دارند اما استفاده از این دسترسی مجاز نیست.
- Overriding تابع مجاز است در صورتی که امضای تابع ثابت بماند و تغییر نکند. در صورت ایجاد اختلاف در پارامترهای خروجی، کامپایل کردن قرارداد شکست خواهد خورد.
- ما میتوانیم از طریق کلمه کلیدی super یا از طریق نام قرارداد super، یک تابع قرارداد super را فراخوانی کنیم.
- در موارد وراثت چندگانه، فراخوانی تابع از طریق کلمه کلیدی super را بیشتر از قراردادهای مشتق ترجیح میدهد.
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 |
pragma solidity ^0.5.0; contract C { //private state variable uint private data; //public state variable uint public info; //constructor constructor() public { info = 10; } //private function function increment(uint a) private pure returns(uint) { return a + 1; } //public function function updateData(uint a) public { data = a; } function getData() public view returns(uint) { return data; } function compute(uint a, uint b) internal pure returns (uint) { return a + b; } } //Derived Contract contract E is C { uint private result; C private c; constructor() public { c = new C(); } function getComputedResult() public { result = compute(3, 5); } function getResult() public view returns(uint) { return result; } function getData() public view returns(uint) { return c.info(); } } |
شرایط کلی وراثت در قراردادهای هوشمند Solidity
وراثت در سالیدیتی شرایطی دارد که میتوان آنها را در موارد زیر خلاصه کرد:
- سالیدیتی از وراثت تک سطحی و همچنین چندگانه پشتیبانی میکند و قراردادها میتوانند با استفاده از کلمه کلیدی is ویژگیهای قراردادهای دیگری را به ارث ببرند.
- تابعی که قرار است با قرارداد فرزند override شود، باید با عنوان virtual اعلام شود.
- تابعی که قرار است یک تابع والد را override کند، باید از کلمه کلیدی override استفاده کند.
- ترتیب در وراثت مهم است.
- شما باید قراردادهای والد را به ترتیب از پایهترین قرارداد تا بیشترین مشتق شده فهرست کنید.
به عنوان نمونه قراردادی که شرایط گفته شده در بالا در آن موجود است، میتوانید قرارداد زیر را بررسی کنید و در ریمیکس آن را امتحان کنید.
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 55 56 57 58 59 60 61 |
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; /* Graph of inheritance A / \ B C / \ / F D,E */ contract A { function foo() public pure virtual returns (string memory) { return "A"; } } // Contracts inherit other contracts by using the keyword 'is'. contract B is A { // Override A.foo() function foo() public pure virtual override returns (string memory) { return "B"; } } contract C is A { // Override A.foo() function foo() public pure virtual override returns (string memory) { return "C"; } } // Contracts can inherit from multiple parent contracts. // When a function is called that is defined multiple times in // different contracts, parent contracts are searched from // right to left, and in depth-first manner. contract D is B, C { // D.foo() returns "C" // since C is the right most parent contract with function foo() function foo() public pure override(B, C) returns (string memory) { return super.foo(); } } contract E is C, B { // E.foo() returns "B" // since B is the right most parent contract with function foo() function foo() public pure override(C, B) returns (string memory) { return super.foo(); } } // Inheritance must be ordered from “most base-like” to “most derived”. // Swapping the order of A and B will throw a compilation error. contract F is A, B { function foo() public pure override(A, B) returns (string memory) { return super.foo(); } } |
انواع وراثت در سالیدیتی
وراثت inheritance در سالیدیتی انواع مختلفی دارد که در این بخش آنها را با یک مثال مورد بررسی قرار خواهیم داد.
وراثت تک سطحی Single Inheritance
در وراثت تک سطحی، به ارث بردن ویژگیهای قرارداد هوشمند تنها در یک سطح و از یک قرارداد والد به یک قرارداد فرزند صورت میگیرد. نمونه وراثت تک سطحی را میتوانید در مثال زیر ببینید.
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 |
// Solidity program to // demonstrate // Single Inheritance pragma solidity >=0.4.22 <0.6.0; // Defining contract contract parent{ // Declaring internal // state variable uint internal sum; // Defining external function // to set value of internal // state variable sum function setValue() external { uint a = 10; uint b = 20; sum = a + b; } } // Defining child contract contract child is parent{ // Defining external function // to return value of // internal state variable sum function getValue( ) external view returns(uint) { return sum; } } // Defining calling contract contract caller { // Creating child contract object child cc = new child(); // Defining function to call // setValue and getValue functions function testInheritance( ) public returns (uint) { cc.setValue(); return cc.getValue(); } } |
وراثت چند سطحی Multi-level Inheritance
وراثت چندسطحی نوعی قرارداد تک سطحی است با این تفاوت که رابطه بین قرارداد والد و قرارداد فرزند در بیشتر از یک سطح تکرار میشود. به این ترتیب که قرارداد فرزند ویژگیهای قرارداد والدی را به ارث میبرد که خود ویژگیهای یک قرارداد والد دیگر را به ارث برده است. به بیان سادهتر قرارداد سوم از قرارداد دوم و قرارداد دوم از قرارداد اول منشا گرفته و ویژگیهای خود را به ارث میبرند.
این نوع از وراثت در قراردادهای هوشمند Solidity را در مثال زیر مشاهده میکنید که ویژگیهای قرارداد A به قراردادB به ارث میرسد و قرارداد B به قرارداد C.
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 55 56 57 58 59 60 61 62 63 64 65 66 |
// Solidity program to // demonstrate Multi-Level // Inheritance pragma solidity >=0.4.22 <0.6.0; // Defining parent contract A contract A { // Declaring state variables string internal x; string a = "Geeks" ; string b = "For"; // Defining external function // to return concatenated string function getA() external{ x = string(abi.encodePacked(a, b)); } } // Defining child contract B // inheriting parent contract A contract B is A { // Declaring state variables // of child contract B string public y; string c = "Geeks"; // Defining external function to // return concatenated string function getB() external payable returns( string memory){ y = string(abi.encodePacked(x, c)); } } // Defining child contract C // inheriting parent contract A contract C is B { // Defining external function // returning concatenated string // generated in child contract B function getC() external view returns( string memory){ return y; } } // Defining calling contract contract caller { // Creating object of child C C cc = new C(); // Defining public function to // return final concatenated string function testInheritance( ) public returns ( string memory) { cc.getA(); cc.getB(); return cc.getC(); } } |
وراثت سلسله مراتبی Hierarchical Inheritance
در تعریف وراثت سلسله مراتبی میتوان گفت که بیشتر از یک قرارداد فرزند از یک قرارداد والد منشا میگیرند. این نوع از وراثت در سالیدیتی بیشتر در زمانهایی کاربرد دارد که بخواهیم از یک عملکرد مشترک در مکانهایی مختلف بهره ببریم. وراثت سلسله مراتبی را در مثال زیر راحتتر درک خواهید کرد، در این مثال ویژگیهای قراردادA به قرارداد B و همچنین به قرارداد C به ارث میرسد.
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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
// Solidity program to demonstrate // Hierarchical Inheritance pragma solidity >=0.4.22 <0.6.0; // Defining parent contract A contract A { // Declaring internal // state variable string internal x; // Defining external function // to set value of // internalstate variable function getA() external { x = "GeeksForGeeks"; } // Declaring internal // state variable uint internal sum; // Defining external function // to set the value of // internal state variable sum function setA() external { uint a = 10; uint b = 20; sum = a + b; } } // Defining child contract B // inheriting parent contract A contract B is A { // Defining external function to // return state variable x function getAstr( ) external view returns(string memory){ return x; } } // Defining child contract C // inheriting parent contract A contract C is A { // Defining external function to // return state variable sum function getAValue( ) external view returns(uint){ return sum; } } // Defining calling contract contract caller { // Creating object of contract B B contractB = new B(); // Creating object of contract C C contractC = new C(); // Defining public function to // return values of state variables // x and sum function testInheritance( ) public returns ( string memory, uint) { return ( contractB.getAstr(), contractC.getAValue()); } } |
وراثت چندگانه Multiple Inheritance
مثالی از یک وراثت چندگانه را نیز در ادامه میتوانید ببینید، وراثت چندگانه در سالیدیتی زمانی اتفاق میافتد که یک قرارداد والد بیشتر از یک قرارداد فرزند داشته باشد و در عین حال قرارداد فرزند هم میتواند بیشتر از یک والد داشته باشد. در قطعه کدنویسی زیر ویژگیهای قرارداد A به قرارداد B به ارث میرسد و قرارداد C از قرارداد A و هم قرارداد B ویژگیها را به ارث میبرد. به بیان دیگر قرارداد C در یک زمان از دو قرارداد A و B ارثبری دارد.
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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
// Solidity program to // demonstrate // Multiple Inheritance pragma solidity >=0.4.22 <0.6.0; // Defining contract A contract A { // Declaring internal // state variable string internal x; // Defining external function // to set value of // internal state variable x function setA() external { x = "GeeksForGeeks"; } } // Defining contract B contract B { // Declaring internal // state variable uint internal pow; // Defining external function // to set value of internal // state variable pow function setB() external { uint a = 2; uint b = 20; pow = a ** b; } } // Defining child contract C // inheriting parent contract // A and B contract C is A, B { // Defining external function // to return state variable x function getStr( ) external returns(string memory) { return x; } // Defining external function // to return state variable pow function getPow( ) external returns(uint) { return pow; } } // Defining calling contract contract caller { // Creating object of contract C C contractC = new C(); // Defining public function to // return values from functions // getStr and getPow function testInheritance( ) public returns(string memory, uint) { contractC.setA(); contractC.setB(); return ( contractC.getStr(), contractC.getPow()); } } |
سخن آخر
وراثت در قراردادهای هوشمند Solidity این امکان را برای برنامهنویس فراهم میکند تا چندین قرارداد را در یک قرارداد ترکیب کند. قراردادهایی که به عنوان قرارداد پایه (base) یا قرارداد مادر (parent) شناخته میشوند آنهایی هستند که سایر قراردادها از آنها ارث میبرند. قراردادهایی که ویژگیها و دادهها را به ارث میبرند با عنوان قرارداد مشتق (derived) یا فرزندان (children) شناخته میشوند. وراثت در سالیدیتی در دو نوع کلی وجود دارد که یکی وراثت تک سطحی Single Inheritance و دیگری وراثت چندگانه Multiple Inheritance است که در تمام انواع آن، وراثت موجب ایجاد ارتباط بین قراردادهای والد و فرزند میشود.
در پایان باید یادآوری کنیم که یادگیری زبان برنامهنویسی سالیدیتی برای کسانی که از قبل با زبانهای جاوا اسکریپت، پایتون و یا سی ++ کار کرده باشند بسیار آسان و قابل درک است زیرا شباهتهای زیادی با آنها دارد. با توجه به ارزشمندی اتریوم و گسترش قراردادهای هوشمند در بلاک چین، یادگیری این زبان میتواند فرصتهای مالی ویژهای را برای علاقهمندان به این مباحث ایجاد کند. در کنار یادگیری این زبان برنامهنویسی، افزایش دانش و اطلاعات در خصوص بلاک چین اتریوم نیز ضروری است و شما را زودتر به کسب درآمد در این حوزه میرساند.
منابع معتبر مرتبط:
مطالب زیر را حتما مطالعه کنید
بررسی رفتار توابع View و Pure در سالیدیتی Solidity
توابع Payable در قراردادهای هوشمند Solidity
سالیدیتی Solidity چیست؟
سطح دسترسی Visibility در سالیدیتی Solidity
توابع Function در سالیدیتی Solidity
انواع حافظه در قرارداد هوشمند سالیدیتی
8 دیدگاه
به گفتگوی ما بپیوندید و دیدگاه خود را با ما در میان بگذارید.
سلام عالی بود
مطلب خوبی بود
خیلی دنبال این موضوع بودم
خیلی ممنون از توضیحات خوبتون
مطلب بی نظیری بود
خیلی محتوای خوبی بود مهندس
سلام دوست عزیز
خوشحالم که براتون مفید بوده 🙂
من یکی از کاربران دائمی سایت شما هستم