基于以太坊的智能合約開發Solidity(函數繼承篇)

參考教程:【實戰篇】1、函數重載_嗶哩嗶哩_bilibili

1、函數重載:

pragma solidity ^0.5.17;contract overLoadTest
{//不帶參數function test() public{}//帶一個參數function test(address account) public{}//參數類型不同,雖然uint160可以和address直接轉化,但仍然滿足重載的條件 function test(uint160 account) public{}//參數個數不同function test(uint160 account,address otherAccount) public{}// 此函數會編譯報錯,因為重載不考慮函數的返回值類型是否相同// function test(address account) returns(address sender){// ? ? return msg.sender;// }uint public result = 0; function negativeExample1(uint id) public{result = 100; }function negativeExample1(uint8 id) public{result = 200;}function test1() public{//negativeExample1(1); ?該語句會報錯,因為傳入函數的參數1既符合uint又符合uint8,        solidity無法辨別調用哪一個函數}function negativeExample2(address account) public{result = 100;}function negativeExample2(uint160 account) public {result = 200;}function test2() public{//negativeExample2(1); ?該語句會報錯,address本質上就是一個uint160的一串數字,solidity無法辨別調用哪一個函數}
}

當一些行為模式一致,但是這個行為所輸入的參數不一樣時,便構成了重載,具體表現如下:

①函數的名字相同

②函數的參數不同(類型、數量)

③與函數的返回值無關

2、函數命名參數:

pragma solidity ^0.5.17;contract functionParamTest
{uint public id;string public name;function setParam(uint _id,string memory _name) public {id = _id;name = _name;}function test() public{setParam(18,"xiaofang"); ?//正常地傳參}function test2() public{setParam({_id:18,_name:"xiaofang"}); ?//通過形參名給函數傳參}function test3() public{setParam({_name:"xiaofang",_id:18}); ?//順序可以與定義函數參數時不同(在較多參數情況下命名參數對于代碼的可讀性有很好的提升)} ?function test4() public{setParam(18); ?//調用函數傳參時不可缺少參數,否則編譯會報錯(在外部調用函數時可以缺少參數,但不建議缺少)}
}

3、函數返回值的特性:

pragma solidity ^0.5.17;contract functionReturnTest
{//最常規的返回值寫法 ?function test() public view returns(uint){return 10;}//返回值也可以進行一個命名,在returns后可以聲明返回值的名稱function test1() public view returns(uint result){result = 1;return result; ?//如果不寫這條語句也是可以的,因為有聲明過返回值的名稱(但不建議搞花里胡哨)}//可以返回任意匹配類型的值(類型必須匹配,名稱不匹配沒關系)function test2() public view returns(uint result){ uint a = 10;result = 100;return a;}//可以返回多個參數,在聲明了返回值名稱的情況下可以不用寫return語句,但必須要給返回值賦值function test3(uint a,uint b) public view returns(uint add,uint multiply){add = a+b;multiply = a*b;}//返回多個參數時return語句要加括號function test4(uint a,uint b) public view returns(uint add,uint ?multiply){return (a+b,a*b);}//可以利用多返回值的特性直接進行數據交換操作function test5(uint a,uint b) public view returns(uint _b, uint _a){return (b,a);}}

4、變量的生命周期與作用域:

(1)作用域:在程序中有非常多的花括號,變量定義在哪對花括號中,那么這對花括號所包含的就是變量的作用域,變量可以在其作用域內有效使用。(注意,函數形參的作用域是函數內部,雖然它看起來不是定義在函數體內部)

(2)生命周期:從變量被分配空間到空間被收回的這一個時間段,稱為變量的生命周期,變量的生命周期自其被定義開始,至其作用域尾部結束(沒有進行手動銷毀的話)。

5、值傳遞與副本拷貝:

pragma solidity ^0.5.17;contract transferValueTest
{uint public a = 200;uint public b = a; ? //將a的值賦給b,但是a和b各自占有不同的空間function changIt() public{b = 400; ?//改變b的值,并不影響a}//i作為形式參數,當調用該函數時,是將所傳值的副本傳入的,并不會改變所傳引用的值,也就是說,對i做修改并不影響a的值function changeIt3(uint i) public returns(uint){i++;return i++;}function test() public {changeIt3(a);}}

6、const靜態修飾:

pragma solidity ^0.5.17;contract constantTest
{// 在0.4版本中,constant等同于view,在0.5以上的版本中已經廢棄/*function test() public constant returns(uint){return 100;}*/
}

7、構造函數:

pragma solidity ^0.5.17;contract constructorTest
{//初始化結果為0uint public a;//構造函數的名稱與合約名相同,在合約部署(或者被創建)的時候執行(0.5以下版本支持該種語法)/*function constructorTest(){a = 100;}*///一個合約內部不能有多個構造函數/*function constructorTest(uint _a,uint _b){a = _a;}*///在0.5以上版本中,solidity采用了關鍵字constructor來定義構造函數constructor() public{a = 100;}/*address public ower;function constructorTest()  在合約部署時,可以借助構造函數傳遞一些內容到合約內,例如部署合約的賬戶{ower = msg.sender;}*/
}

8、函數修改器modifire:

(1)基本用法:

pragma solidity ^0.5.17;contract modifireTest
{address public ower;uint public num = 0;constructor() public{ower = msg.sender;}//定義一個函數修改器 modifier onlyOwer{require(msg.sender == ower);  //不符合條件時則拋出異常,停止執行下面的語句并回滾//修飾函數時,函數相當于被插入到'_;'位置,然后把onlyOwer當作函數執行_;}function changeIt(uint _num) public onlyOwer{num = _num;  //該例中只有部署該合約的賬戶才有權利調用這個函數,其它賬戶調用該函數將會報錯//當然,“require(msg.sender == ower);”也可以直接寫在該函數中,這樣就不需要借助modifier}}

Solidity的異常處理:

①Solidity使用“狀態恢復異常”來處理異常。這樣的異常將撤消對當前調用(及其所有子調用)中的狀態所做的所有更改,并且向調用者返回錯誤。

②函數assert和require可用于判斷條件,并在不滿足條件時拋出異常

? assert() 一般只應用于測試內部錯誤,并檢查常量

? require() 應用于確保滿足有效條件,或驗證調用外部合約的返回值

? revert() 用于拋出異常,它可以標記一個錯誤并將當前調用回退

(2)運用示例1:

pragma solidity ^0.5.17;contract mappingTest
{//一個錢包地址對應一個個人身份id mapping(address => uint) idMapping;//一個人的身份id地址對應一個人的姓名mapping(uint => string) nameMapping;uint id = 0;address public ower;//定義一個函數修改器 modifier onlyOwer{require(idMapping[msg.sender] == 0); ?//判斷調用函數的賬戶有沒有綁定身份的記錄,以免同一賬戶注冊多個身份//修飾函數時,函數相當于被插入到'_;'位置,然后把onlyOwer當作函數執行_;}function register(string memory name) public onlyOwer //該函數模擬新賬戶綁定身份{address account = msg.sender; ?//調用該函數的賬戶為需要綁定身份和生成id號的新賬戶id++; ?//這里的id號應該是隨機生成,總之每個調用該函數的賬戶都應該獲得不同的id號//給賬戶分配一個ididMapping[account] = id;//再將個人id與個人姓名進行映射綁定nameMapping[id] = name; }//根據賬戶地址獲取idfunction getIdByAddress(address account) public view returns(uint){return idMapping[account];}//根據id獲取個人姓名function getNameById(uint id) public view returns(string memory){return nameMapping[id];}

(3)運用示例2:

pragma solidity ^0.5.17;contract modifireTest
{uint level = 200;uint money = 0;modifier modifyLevel(uint _inputLevel) ?//函數修改器可以有參數,這樣使用起來更加靈活{require(level >= _inputLevel, "Your level is not within the range!");//如不滿足require中的條件,錯誤類型為Your level is not within the range_;}function addMoney() modifyLevel(50) public {//require(level >= 50); ?五十級以上才能調用該函數money = 100;}function recoverCash() modifyLevel(200) public {//require(level >= 200); ?兩百級以上才能調用該函數money = 200;}function getMoney() public view returns(uint) {return money;}}

(4)多重modifire的執行順序:

pragma solidity ^0.5.17;contract modifireTest4
{uint public a = 0;modifier mod1{a = 1; ?//執行順序——1(最先執行)_;a = 2; ?//執行順序——5(最后執行)}modifier mod2{a = 3; ?//執行順序——2_;a = 4; ?//執行順序——4}function test() public mod1 mod2 ?//調用該函數后,a的值為2{a = 100; ?//執行順序——3}}

9、合約的繼承:

(1)基本的繼承:

pragma solidity ^0.5.17;contract Father
{uint money = 10000;function noSmoking() public view returns(string memory){return "I'm not somking";}
}contract Son is Father ?//繼承語法:contract 子類名稱 is 父類名稱1,父類名稱2……
{function getMoney() public view returns(uint){return money; ?//子類繼承了父類中的屬性
}function test() public view returns(string memory){return noSmoking(); ?//子類繼承了父類中的函數}
}

(2)連續繼承:

pragma solidity ^0.5.17;contract GrandFather
{uint height = 170;
}contract Father is GrandFather
{uint money = 10000;function getHeight() public view returns(uint){return height; ?//子類繼承了父類中的屬性}
}contract Son is Father
{function getHeight() public view returns(uint){return height; ?//子類繼承了父類的父類中的屬性}
}

(3)繼承權限:

①合約屬性的繼承:

pragma solidity ^0.5.17;contract Father
{uint private privateMoney = 2000; ?//加上private標識的屬性或函數不會被子類繼承//其余情況下可以被繼承//uint privateMoney = 2000;//uint public privateMoney = 2000;//uint internal privateMoney = 2000;//注意:external不能修飾屬性,只修飾函數uint money = 10000;function noSmoking() public view returns(string memory){return "I'm not somking";}}contract Son is Father
{function getMoney() public view returns(uint){return money; ?//正常“財產”可以被繼承
}function getPrivateMoney() public view returns(uint){//return privateMoney; ?父類的私房錢子類無法繼承
}}

②public修飾父類函數:

pragma solidity ^0.5.17;contract Father
{function noSmoking() public view returns(string memory){return "I'm not somking";}}contract Son is Father
{function test() public view returns(string memory){return noSmoking(); ?//子合約可以正常調用父類中public修飾的函數}}

③private修飾父類函數:

pragma solidity ^0.5.17;contract Father
{function noSmoking() private view returns(string memory){return "I'm not somking";}}contract Son is Father
{function test() public view returns(string memory){//return noSmoking(); ?子合約不可以調用父類中private修飾的函數}}

④internal修飾父類函數:

pragma solidity ^0.5.17;contract Father
{function noSmoking() internal pure returns(string memory){return "I'm not somking";
}function test() public returns(string memory){return noSmoking(); ?//被internal修飾的函數,只能在合約內部以及子合約中被調用,外部無法直接調用}}contract Son is Father
{function test2() public pure returns(string memory){return noSmoking(); ?//子合約可以正常調用父類中internal修飾的函數(當然,也只能在合約內部調用,外部不可見)}}

⑤external修飾父類函數:

pragma solidity ^0.5.17;contract Father
{function noSmoking() external pure returns(string memory){return "I'm not somking";}function test() public returns(string memory){//return noSmoking(); ?被external修飾的函數,只能在外部被調用,合約內部以及子合約中無法直接調用return this.noSmoking(); ?//通過this可以讓編譯器認為這是在外部通過該合約地址調用該函數,這樣就不會報錯}}contract Son is Father
{function test2() public view returns(string memory)  //使用this的話,千萬不要使用pure{//return noSmoking();return this.noSmoking(); ?//子類也可以通過this調用父類中external修飾的函數}}contract Mother
{function test() public returns(string memory){Father f = new Father(); ?//對于被external修飾的函數,在其它非子合約中可以直接創建合約對象,通過合約對象進行外部調用return f.noSmoking();}}

10、全局變量自動getter函數:

(1)普通變量的get方法:

pragma solidity ^0.5.17;contract GetterTest
{uint public num = 100; ?//public修飾符修飾的屬性,默認會生成一個get方法,供我們外部調用/*function num() external returns(uint) ?{return num;}1、變量用public修飾后,這個函數就是生成的get方法(函數體內部定義的變量不能用public修飾)2、默認生成的get函數是external權限的,不能夠在合約的內部調用3、對于該例,num()方法只能有一個,要是自己進行重寫,就會覆蓋默認生成的get方法*/function test() public{// num();this.num(); ?//可以通過this對get方法進行外部調用}}

(2)mapping類型數據的get方法:

pragma solidity ^0.4.18;  //編譯器版本與前面例子所用的不同contract GetterTest
{mapping(uint => string) public map;function map(uint key) external returns(string) ?//map的get方法(需傳入key值才能獲取value值,對于嵌套的mapping,就需要傳入多個key值){return map[key];}}

補充——mapping映射:

pragma solidity ^0.5.17;contract mappingTest
{//個人認為這個有點像Python中的字典(可以理解為mapping(key => value) 字典名)//一個錢包地址對應一個個人身份id mapping(address => uint) idMapping;//一個人的身份id地址對應一個人的姓名mapping(uint => string) nameMapping;uint id = 0;function register(string memory name) public //該函數模擬新賬戶綁定身份{address account = msg.sender; ?//調用該函數的賬戶為需要綁定身份和生成id號的新賬戶id++; ?//這里的id號應該是隨機生成,總之每個調用該函數的賬戶都應該獲得不同的id號//給賬戶分配一個ididMapping[account] = id;//再將個人id與個人姓名進行映射綁定nameMapping[id] = name; ? ? ? ?}//根據賬戶地址獲取idfunction getIdByAddress(address account) public view returns(uint){return idMapping[account];}//根據id獲取個人姓名function getNameById(uint id) public view returns(string memory){return nameMapping[id];
}mapping(uint => mapping(uint => mapping(uint => string))) public map;function test() public{map[0][1][1] = "lalalalala"; ?//mapping數據類型還可以嵌套,相當于Python中的多維字典//map[0]:mapping(uint => mapping(uint => string))//map[0][1]:mapping(uint => string)//map[0][1][1]:string}}

mapping(key => value) Mapping的相關語句:

(1)“mapping(type1 => type2) Mapping;”的作用是創建一個type1類型到type2類型的映射,映射組的名稱為“Mapping”。

(2)“Mapping[key] = value;”的作用是:

①如果Mapping組中此前沒有key這個鍵值,那么Mapping組中會添加key這個鍵值到value的映射。

②如果Mapping組中此前存在key這個鍵值,那么key鍵值的映射修改為value。

11、繼承中的重寫:

(1)屬性重寫:

pragma solidity ^0.5.17;contract Father
{uint money = 10000;uint public height = 170; ?//父類屬性用public修飾,那么子類繼承后會生成get方法,調用該方法會獲取父類的height而不是子類的}contract Son is Father
{uint money = 20000; ?//子類重寫了父類的money,以子類為準(但是不影響父類的money)uint height = 180; ?//子類重寫了父類的height,那么子類使用height時將以此為準(如果用public修飾該屬性,那么此處生成的get方法會將父類生成的get方法覆蓋,調用該方法會獲取子類的height)function getMoney() public view returns(uint){return money;}function getHeight() public view returns(uint){return height;
}}

(2)函數重寫:

pragma solidity ^0.5.17;contract Father
{uint public money = 10000;function noSmoking() public view returns(string memory){return "I don't smoke,and I do not drink";}
}contract Son is Father
{uint public money = 20000;function noSmoking() public view returns(string memory) ?//子類重寫了父類的函數,父類函數將會被覆蓋{return "I do not smoke,but I do drink";}function test() public view returns(string memory){return noSmoking();}
}

12、多繼承需要注意的情況:

pragma solidity ^0.5.17;contract Father
{uint public money = 10000;uint public height = 180;}contract Mother
{uint public money = 20000;uint public height ?= 170;uint public weight = 120;}contract Son is Father,Mother
{function test() public view returns(uint){return height; ?//會返回Mother中的height,后繼承的屬性如果與前面繼承的相同,前繼承的屬性將會被覆蓋}}

13、合約的銷毀(析構函數):

pragma solidity ^0.5.17;contract DestructTest
{address ower;constructor() public{ower = msg.sender;}uint public money = 100;function increment() public{money += 100;}function kill() public{if(msg.sender == ower) ?//只有發布合約的賬戶有權利銷毀合約{//手動進行自我銷毀selfdestruct(msg.sender);}} ? ?
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/210752.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/210752.shtml
英文地址,請注明出處:http://en.pswp.cn/news/210752.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

發送、接收消息,界面不及時刷新

發送、接收消息后 UI 沒展示,不及時刷新,大概率 是 SDK 的 UI 刷新功能被干擾,參考下面排查: 檢查 initWithAppkey 和 connectWithToken 使用的是否是 IMKit 核心類 RCIM 的方法,如果不是,請換成 RCIM 的。…

【刷題】位運算

2 n 2^n 2n 1<<n判斷某一位是否為1 s&1<<k將上面兩個組合&#xff0c;可以得到判斷一個集合中哪些內容包含&#xff0c;遍歷所有情況。 100140. 關閉分部的可行集合數目 一個公司在全國有 n 個分部&#xff0c;它們之間有的有道路連接。一開始&#xff0c;…

CentOS 7 離線安裝達夢數據庫8.0

前期準備工作 確認操作系統的版本和數據庫的版本是否一致 ## 查看系統版本&#xff1a;cat /etc/redhat-release CentOS Linux release 7.5.1804 (Core)關閉防火墻和Selinux # 查看selinux是不是disabled / enforce cat /etc/selinux/config## 查看防火墻狀態 firewall-cmd …

數據結構之歸并排序及排序總結

目錄 歸并排序 歸并排序的時間復雜度 排序的穩定性 排序總結 歸并排序 歸并排序大家只需要掌握其遞歸方法即可&#xff0c;非遞歸方法由于在某些特殊場景下邊界難控制&#xff0c;我們一般很少使用非遞歸實現歸并排序。那么歸并排序的遞歸方法我們究竟是怎樣實現呢&#xff…

PHP醫院手術麻醉系統源碼,laravel、vue2 、mysql技術開發,自主知識產權,二開快捷

醫院手術麻醉系統全套源碼&#xff0c;有演示&#xff0c;自主知識產權 技術架構&#xff1a;PHP、 js 、mysql、laravel、vue2 手術麻醉臨床信息管理系統是數字化手段應用于手術過程中的重要組成部分&#xff0c;用數字形式獲取并存儲手術相關信息&#xff0c;既便捷又高效。…

每日一練2023.12.10—— 倒數第N個字符串【PTA】

題目鏈接&#xff1a;L1-050 倒數第N個字符串 題目要求&#xff1a; 給定一個完全由小寫英文字母組成的字符串等差遞增序列&#xff0c;該序列中的每個字符串的長度固定為 L&#xff0c;從 L 個 a 開始&#xff0c;以 1 為步長遞增。例如當 L 為 3 時&#xff0c;序列為 { a…

Qt Creator設置IDE的字體、顏色、主題樣式

Qt是一款開源的、跨平臺的C開發框架&#xff0c;支持Windows、Linux、Mac系統&#xff0c;從1995發布第一版以來&#xff0c;發展迅猛&#xff0c;最開始是用于Nokia手機的Symbian(塞班)系統和應用程序開發&#xff0c;現在是用于嵌入式軟件、桌面軟件(比如WPS、VirtualBox)、A…

【圖論筆記】克魯斯卡爾算法(Kruskal)求最小生成樹

【圖論筆記】克魯斯卡爾算法&#xff08;Kruskal&#xff09;求最小生成樹 適用于 克魯斯卡爾適合用來求邊比較稀疏的圖的最小生成樹 簡記&#xff1a; 將邊按照升序排序&#xff0c;選取n-1條邊&#xff0c;連通n個頂點。 添加一條邊的時候&#xff0c;如何判斷能不能添加…

Python實現PDF-Excel

輕松解決PDF格式轉Excel&#xff08;使用python實現&#xff09; 實現思路&#xff1a; 要將PDF轉換為Excel&#xff0c;可以使用以下步驟&#xff1a; 解析PDF內容&#xff1a;首先&#xff0c;需要使用Python中的第三方庫&#xff08;如PyPDF2、pdfminer等&#xff09;來解…

西南科技大學C++程序設計實驗十二(文件流操作)

一、實驗目的 1. 熟悉文件的基本操作; 2. 在類中添加打開文件、保存文件、讀取文件等處理函數; 二、實驗任務 1. 分析完善程序:主函數創建一個文件對象,每次打開文件,在其尾部添加數據。如果文件不存在,則新建該文件。請將空白處需要完善的功能補充完整。 #include …

mybatis-config.xml的配置

1&#xff1a;MyBatis 的常規配置文件 mybatis-config.xml 包含了對 MyBatis 框架的全局配置&#xff0c;下面是一個常見的示例&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD…

Java代碼重構技巧:提高可維護性和可擴展性

引言&#xff1a; 在軟件開發過程中&#xff0c;代碼重構是一項非常重要的任務。通過對代碼進行重構&#xff0c;可以提高代碼的可維護性和可擴展性&#xff0c;減少代碼的復雜度&#xff0c;增加代碼的可讀性和可測試性。本文將介紹一些常用的Java代碼重構技巧&#xff0c;幫助…

HTML中表格的語法及使用(詳解)

Hi i,m JinXiang ? 前言 ? 本篇文章主要介紹HTML中表格的語法及詳細使用以及部分理論知識 &#x1f349;歡迎點贊 &#x1f44d; 收藏 ?留言評論 &#x1f4dd;私信必回喲&#x1f601; &#x1f349;博主收將持續更新學習記錄獲&#xff0c;友友們有任何問題可以在評論區留…

Java集合框架定義以及整體結構

目錄 一、Java集合框架1.1 什么是java集合框架1.2 集合與數組 二、集合框架具體內容2.1 整體框架2.2 遺留類和遺留接口1.3 集合框架設計特點 參考資料 一、Java集合框架 1.1 什么是java集合框架 Java集合框架&#xff08;Java Collections Framework&#xff09;是Java平臺提…

高云GW1NSR-4C開發板上手使用

1.開發板 核心板&#xff0c;主芯片GW1NSR-LV4CQN48P&#xff0c;絲印文字“奧陶紀Octet&#xff0c;QQ群808770961”&#xff1a; 晶振&#xff1a;27MHz&#xff0c;22引腳 兩個按鍵&#xff1a;靠近中間&#xff0c;23引腳&#xff0c;按下為低電平&#xff1b;靠近外側&…

Flink 讀寫 HBase 總結

前言 總結 Flink 讀寫 HBase 版本 Flink 1.15.4HBase 2.0.2Hudi 0.13.0官方文檔 https://nightlies.apache.org/flink/flink-docs-release-1.17/zh/docs/connectors/table/hbase/ Jar包 https://repo1.maven.org/maven2/org/apache/flink/flink-sql-connector-hbase-2.2/1…

[Linux] yum安裝分布式LNMP架構

1. 在一臺主機安裝nginx&#xff08;192.168.136.120&#xff09; 1.1 搭建nginx相關的yum源 cd /yum.repos.d mkdir bak mv *.repo bak vim /etc/yum.repos.d/nginx.repo [nginx-stable] namenginx stable repo baseurlhttp://nginx.org/packages/centos/7/$basearch/ gpgche…

基于Python+Django+mysql圖書管理系統

基于PythonDjangomysql圖書管理系統 一、系統介紹二、功能展示三、其它系統四、獲取源碼 一、系統介紹 程序開發軟件&#xff1a;Pycharm 數據庫&#xff1a;mysql 采用技術&#xff1a; Django(一個MVT框架&#xff0c;類似Java的SSM框架) 人生苦短&#xff0c;我用Python&a…

【rabbitMQ】rabbitMQ的下載,安裝與配置

目錄 1. 下載Erland 安裝步驟&#xff1a; 配置環境變量&#xff1a; 校驗環境變量配置是否成功 2.下載MQ 安裝步驟&#xff1a; 添加可視化插件 &#xff1a; 啟動&#xff1a; 拒絕訪問 1. 下載Erland 因為rabbitMQ是基于Erland,所以在安裝rabbitMQ之前需要安裝Erla…

WPF(Windows Presentation Foundation)的 ToolBar控件

WPF&#xff08;Windows Presentation Foundation&#xff09;的 ToolBar 是一種用于創建工具欄的控件。 工具欄通常位于應用程序窗口的頂部或側邊&#xff0c;并提供了一組常用的工具按鈕或命令&#xff0c;用于執行特定的操作或訪問特定的功能。 ToolBar 控件是 WPF 中的一個…