Go 面向對象OOP思想

Go語言不是面向對象的語言,只是可以采用面向對象的思維通過一些方法來模擬面向對象。面向對象思維核心就三個點:封裝、繼承、多態

GO語言和傳統的面向對象編程有所區別,并不是純粹的面向對象語言。比如C++,Java的面向對象都是基于類的,但是Go沒有類,Go是基于struct來實現OOP特性的。Go去掉了傳統的OOP語言的方法重載、構造函數、析構函數等,但是Go仍然有著面向對象編程的繼承、封裝和多態的特性,只是實現方式比較不同。?

繼承?

繼承需要符合的關系是is-a,父類更通用,子類更具體

子類會具有父類的一般特性,也會具有自身的特性

繼承就是子類繼承父類的特征和行為,使得子類具有父類的屬性和方法。

結構體嵌套?

package mainimport "fmt"// 定義一個父類
type Person struct {name stringage  int
}// 定義一個子類,Student擁有了父類所有的屬性,還有自己的特性
type Student struct {Person // 匿名字段,實現了繼承。school string
}func main() {// 1、 創建父類對象p1 := Person{name: "Autumn", age: 18}fmt.Println(p1)fmt.Println(p1.name, p1.age)// 2、創建子類s1 := Student{Person: Person{name: "小明", age: 3}, school: "清華"}fmt.Println(s1)fmt.Println(s1.Person.name, s1.Person.age, s1.school)// 3、創建子類var s2 Students2.Person.name = "張三"s2.Person.age = 3s2.school = "北大"fmt.Println(s2)// 概念:提升字段, 只有匿名字段才可以做到// Person 在Student中是一個匿名字段, Person中的屬性 name age 就是提升字段// 所有的提升字段就可以直接使用了,不同在通過匿名字段來點了var s3 Students3.name = "李四"s3.age = 4s3.school = "清華"fmt.Println(s3)fmt.Println(s3.name, s3.age)
}

????????繼承就是子類繼承父類的特征和行為,使得子類具有父類的屬性和方法,使得子類具有父類相同的行為。子類會具有父類的一般特性也會具有自身的特性。

方法&函數

Go語言中同時擁有函數和方法。一定要和其他只有方法的語言區分開?

方法:需要指定調用者,約定這個方法屬于誰的. ? 對象.方法()

函數:不需要指定調用者,定義了函數就可以直接函數名()調用

  • 方法可以重名,只需要調用者不同

  • 如果調用者相同則不可重名

  • func (方法調用者)(方法名)(){}

package mainimport "fmt"// 方法:可以理解為函數多了一個調用者
// 方法可以重名,不同的對象,調用的結果是不一樣的
type Dog struct {name stringage  int
}// 方法定義,   func 方法調用者  方法名()
// 1、方法可以重名,只需要調用者不同
// 2、如果調用者相同,則不能重名
func (dog Dog) eat() {fmt.Println("Dog eating...")
}func (dog Dog) sleep() {fmt.Println("Dog sleep...")
}type Cat struct {name stringage  int
}func (cat Cat) eat() {fmt.Println("Cat eating...")
}
func (cat Cat) sleep() {fmt.Println("Cat sleep...")
}func main() {// 創建一個對象dog := Dog{name: "旺財",age:  2,}fmt.Println(dog)// 方法的調用,通過對應的結構體對象來調用dog.eat()cat := Cat{name: "喵喵",age:  1,}cat.eat()
}

?方法:

  • 某個類的行為功能,需要指定調用者

  • 一段獨立的代碼功能,必須要使用調用者來調用

  • 多個類的方法可以重名,單個類不行

  • 方法是某個類的動作

函數:

  • 一段獨立的代碼功能,可以直接調用

  • 命名完全不能沖突

  • 函數是一個特殊的類型

方法的重寫

  • 子類可以重寫父類的方法

  • 子類還可以有自己新增的方法

  • 子類可以訪問父類中的屬性和方法

package mainimport ("fmt"
)// 方法重寫,建立在父類和子類結構上的
type Animal struct {name stringage  int
}func (animal Animal) eat() {fmt.Println(animal.name, " 正在eating...")
}
func (animal Animal) sleep() {fmt.Println(animal.name, " 正在sleeping....")
}// 子類
type Dog struct {Animal
}// 子類自己的方法
func (dog Dog) wang() {fmt.Println("wangwangwanwg~~~")
}type Cat struct {Animalcolor string // 子類可以定義自己的屬性
}// 子類重寫父類的方法 , 子類的方法名和父類同名,即可重寫父類的方法
func (cat Cat) eat() {fmt.Println(cat.name, " 正在吃cat....")
}func main() {// 定義一個子類,使用父類方法dog := Dog{Animal{name: "旺財", age: 3}}dog.eat()  // 調用父類的方法dog.wang() // 調用自己擴展的方法cat := Cat{Animal{name: "煤球", age: 3}, "黑色"}cat.eat() // 如果重寫了父類的方法就是調用子類自己的方法fmt.Println(cat.color) // 調用子類自己的屬性// 子類可以操作父類的方法,父類可以操作子類的嗎?不可以// 父類不能調用子類自己的擴展的方法a := Animal{name: "大黃", age: 3}a.eat()a.sleep()
}

?接口

  • 接口就是把一些共性的方法集合在一起定義

  • 如果有實現類將接口定的方法全部實現了,那么就代表實現了這個接口

  • 接口是方法的定義集合,不需要實現具體的方法內容?

package mainimport ("fmt"
)// 接口的定義 interface 來定義,方法太多了,要歸類,方法的集合
type USB interface { // 接口,方法的集合input()  // 輸入方法output() // 輸出方法
}// 鼠標
type Mouse struct {name  stringprice float64
}// 鍵盤
type KeyBoard struct {name  stringprice float64
}// 結構體實現了接口的全部方法就代表實現了這個接口,否則不算實現這個接口
func (mouse Mouse) output() {fmt.Println(mouse.name, "鼠標輸出")
}
func (mouse Mouse) input() {fmt.Println(mouse.name, "鼠標輸入")
}// 結構體實現了接口的全部方法就代表實現了這個接口,否則不算實現這個接口
func (keyboard KeyBoard) output() {fmt.Println(keyboard.name, "鍵盤輸入")
}
func (keyboard KeyBoard) input() {fmt.Println(keyboard.name, "鍵盤輸入")
}// 接口的測試
func test(u USB) {u.input()u.output()
}func main() {// 通過傳入接口實現類來進行調用,這樣靈活,減少臃腫m := Mouse{name: "華為鼠標"}// test 參數 USB 類型,傳入Mouse也可以呢?因為一個結構體實現了這個接口所有的方法,那這個結構體就是這個接口類型的test(m)k := KeyBoard{name: "小米鍵盤"}test(k)// 定義高級類型  k就升級了  KeyBoard --> USB  向上轉型var usb USBusb = kfmt.Println(usb)// 接口是無法使用實現類的屬性的//fmt.Println(usb.name)
}

空接口

  • 不包含任何方法:空接口沒有定義任何方法,因此它可以接受任何類型的值。

  • 所有類型包括結構體都默認實現了空接口:Go 中的所有類型都隱式地滿足了空接口類型。

  • 空接口可以存儲任何的類型:空接口在需要處理未知類型或者多種類型的場景下非常有用。

  • 類型斷言:從空接口中取出一個值時,通常需要使用類型斷言來確定該值的具體類型,以便進行類型安全的訪問。

  • 反射:空接口與反射機制緊密相關,通過反射可以檢查存儲在空接口中的值的類型,并進行相應的操作。

不包含任何方法:??
package mainimport "fmt"func doSomething(i interface{}) {// 空接口i可以接收任何類型的參數,但這里我們不能對它執行任何方法調用fmt.Println("用任何類型的值做某事")
}func main() {doSomething(42)doSomething("hello")doSomething(true)
}
所有類型默認實現了空接口
package mainimport "fmt"func main() {// 所有這些類型都隱式地實現了空接口var i interface{} = 42      // intvar j interface{} = "hello" // stringvar k interface{} = true    // boolfmt.Println(i, j, k)
}

?存儲任何類型:?

package mainimport "fmt"func storeValue(i interface{}) {// 這個函數可以使用空接口存儲任何類型的值fmt.Printf("Stored value: %v\n", i)
}func main() {storeValue(123)storeValue("Go is great!")storeValue(3.14)
}

類型斷言

?

package mainimport "fmt"func process(i interface{}) {// 使用類型斷言將空接口中的值轉換為具體類型if s, ok := i.(string); ok {fmt.Println("是字符串類型:", s)} else {fmt.Println("不是字符串類型")}if s, ok := i.(int); ok {fmt.Println("是int類型:", s)} else {fmt.Println("不是int類型")}
}func main() {process("hello")process(42) // 這將輸出 "Not a string"
}

反射

?

package mainimport ("fmt""reflect"
)func inspect(i interface{}) {// 使用反射檢查空接口中的值v := reflect.ValueOf(i)fmt.Printf("Type: %s, Value: %v\n", v.Type(), v.Interface())
}func main() {inspect("hello")inspect(123)inspect(3.14)
}

多態:Go語言中是模擬多態?

一個事物有多種形態?

package mainimport "fmt"// 定義接口
type Animal interface {eat()sleep()
}type Dog struct {name string
}func (dog Dog) eat() {fmt.Println(dog.name, "Doc--eat")
}
func (dog Dog) sleep() {fmt.Println(dog.name, "Doc--sleep")
}// 接口的測試
func test(animal Animal) {animal.eat()animal.sleep()
}// 多態
func main() {// Dog 兩重身份:1、Dog   2、Animal ,多態dog := Dog{name: "旺財"}dog.eat()dog.sleep()// Dog 也可以是 Animal// test 參數 Animal 類型,傳入Dog也可以呢?因為一個結構體實現了這個接口所有的方法,那這個結構體就是這個接口類型的test(dog)// 定義一個類型可以為接口類型的變量// 實際上所有實現類都可以賦值給這個對象var animal Animal // 模糊的 -- 具體化,將具體的實現類賦值給他,才有意義animal = dogtest(animal)
}

?

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

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

相關文章

匯聚榮科技:拼多多開店沒有流量應該怎么辦?

拼多多開店沒有流量是一個常見的問題,許多新手商家都會遇到這樣的困境。那么,如何解決這個問題呢?下面從四個方面進行詳細闡述。 一、優化店鋪和商品 首先,要確保店鋪和商品的質量。店鋪要有自己獨特的風格和特色,商品要有高質量…

Allegro如何輸出各層PCB視圖的PDF文件

如何輸出各層PCB視圖的PDF文件 1、說明 用Allegro設計好PCB后,有時需要出各層的PDF文檔出來進行匯報和展示,這時就需要將各層的平面視圖全部以PDF的形式加載出來,具體方法如下。 2、PDF文件的輸出方法(以四層板為例) …

原子學習筆記7——FrameBuffer 應用編程

Frame 是幀的意思,buffer 是緩沖的意思,所以 Framebuffer 就是幀緩沖,這意味著 Framebuffer 就是一塊內存,里面保存著一幀圖像。 應用程序通過對 LCD 設備節點/dev/fb0(假設 LCD 對應的設備節點是/dev/fb0)…

css如何實現邊框模糊的效果

其實并不難&#xff0c;用屬性 filter: blur(數字px); 即可。效果如下&#xff1a; 圖上的圓形內有色彩的漸變&#xff0c;同樣也是用filter: blur(數字px); 實現的&#xff0c;代碼如下&#xff1a;、 <template><div id"root" :style"{}">…

ros鍵盤控制程序teleop_twist_keyboard 鍵值含義及用法

在機器人仿真中&#xff0c; 經常會用到鍵盤控制程序teleop_twist_keyboard 對機器人進行控制。但是對各個鍵值是何種含義&#xff0c; 如何操作并沒有任何資料介紹,初次使用時會不知所措。 通過實踐&#xff0c; 發現各個鍵值的作用如下&#xff1a; u-- 向左前方前進 i-- 直…

RIP動態路由協議詳解

目錄 一&#xff1a;RIP協議的基本信息 二&#xff1a;RIP協議中的更新方式 三&#xff1a;RIP協議中的計時器 定時更新器&#xff08;UPDATE timer&#xff09; 無效定時器&#xff08;invalid Timer&#xff09; 垃圾收集定時器&#xff08;garbage collection timer&a…

第五課,輸入函數、布爾類型、比較運算和if判斷

一&#xff0c;輸入函數input() 與輸出函數print()相對應的&#xff0c;是輸入函數input()&#xff0c;前者是把程序中的數據展示給外界&#xff08;比如電腦屏幕上&#xff09;&#xff0c;而后者是把外界&#xff08;比如鍵盤&#xff09;的數據輸入進程序中 input()函數可…

Verilog代碼bug:一種特殊的組合邏輯環

Verilog代碼bug&#xff1a;一種特殊的組合邏輯環 組合邏輯環&#xff08;Combinational Loop&#xff09;是什么&#xff0c;別的文章已經寫的很多了&#xff0c;本文就不贅述了&#xff0c;本文主要記錄遇到過的一種特殊的邏輯環&#xff1b; 代碼如下所示&#xff1a; mo…

MacApp自動化測試之Automator初體驗

今天我們繼續講Automator的使用。 初體驗 啟動Automator程序&#xff0c;選擇【工作流程】類型。從資源庫區域依次將獲取指定的URL、從網頁中獲得文本、新建文本文件三個操作拖進工作流創建區域。 然后修改內容&#xff0c;將獲取指定的URL操作中的URL替換成https://www.cnb…

for循環 while循環

for循環 for循環格式 for 變量 in 取值列表 #for in &#xffe5; &#xff08;seq 1 10&#xff09; do 命令序列 .......... done 另一種 for &#xff08;&#xff08;變量初始值&#xff1b; 變量范圍&#xff0c; 變量迭代方…

JDK1.8 安裝并配置環境變量

一、Windows 配置 1 安裝文件 jdk-8u401-windows-i586.exe 2 環境變量 JAVA_HOME C:\Program Files (x86)\Java\jdk-1.8 CLASSPATH .;%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\lib\dt.jar; Path %JAVA_HOME%\bin 說明&#xff1a;Win7/Win8 中 Path 可能需要寫成 ;%JAVA_HO…

C#窗體程序設計筆記:按鈕控件的常用屬性和點擊事件設置

文章目錄 按鈕控件的常用屬性按鈕控件的點擊事件設置 按鈕控件的常用屬性 Text&#xff1a;設置按鈕上顯示的文本內容&#xff1b;Font&#xff1a;設置按鈕上顯示文本所使用的字體&#xff08;包括類型和大小&#xff09;&#xff1b;ForeColor&#xff1a;設置按鈕上顯示的文…

Edge瀏覽器自動翻譯功能按鈕不見了

前言&#xff1a; 平時偶爾會用到Edge的頁面翻譯功能&#xff0c;使用挺方便。突然發現Edge瀏覽器的翻譯功能不見 了。如下圖所示&#xff1a; 解決思路&#xff1a; 1、從網上找各種解決方案也沒有解決&#xff0c;其中有一個說到點右上角的三個點 2、點擊設置…

25_NumPy數組np.round將ndarray舍入為偶數

25_NumPy數組np.round將ndarray舍入為偶數 使用 np.round() 將 NumPy 數組 ndarray 的元素值舍入為任意位數。請注意&#xff0c;0.5 由于舍入到偶數而不是一般舍入而舍入為 0.0。 本文介紹了一般舍入的實現示例。 如何使用 np.round() 基本用法指定要舍入的位數&#xff1a…

30W 寬電壓輸入 AC/DC 導軌式開關電源——TPR/DG-30-XS 系列

TPR/DG-30-XS 系列導軌式開關電源&#xff0c;額定輸出功率為30W&#xff0c;產品輸入范圍&#xff1a;90-264VAC。提供12V、24V輸出&#xff0c;12V輸出時&#xff0c;工作溫度范圍 (-25℃~70℃)具有短路保護&#xff0c;過載保護等功能&#xff0c;并具備高效率&#xff0c;高…

Windows內核--Kernel API簡析(3.1)

如果所有的內核提供的功能&#xff0c;內核提供進程/線程創建和終止&#xff0c;內存分配和釋放&#xff0c;文件操作&#xff0c;網絡功能&#xff0c;驅動程序加載和卸載等功能。這些API將在后面陸續介紹&#xff0c;如下先介紹Kernel提供的基礎API(Kernel自身或Driver使用).…

視頻號小店,一個不用直播就可以變現的項目!創業首選!

大家好&#xff0c;我是電商小V 想要創業或者是想要利用視頻號變現的小伙伴可以說是很多的&#xff0c;因為視頻號這兩年的流量是非常大的&#xff0c;甚至即將超越抖音的流量&#xff0c;因為視頻號背靠騰訊平臺&#xff0c;也是不缺少流量的&#xff0c;并且視頻號的流量是可…

實時“秒回”,像真人一樣語音聊天,GPT-4o模型強到恐怖

今天凌晨OpenAl發布了 GPT-4o&#xff0c;這是一種新的人工智能模式&#xff0c;集合了文本、圖片、視頻、語音的全能模型。 能實時響應用戶的需求&#xff0c;并通過語音來實時回答你&#xff0c;你可以隨時打斷它。還具有視覺能力&#xff0c;能識別物體并根據視覺做出快速的…

6、Qt—Log4Qt使用小記1

開發平臺&#xff1a;Win10 64位 開發環境&#xff1a;Qt Creator 13.0.0 構建環境&#xff1a;Qt 5.15.2 MSVC2019 64位 一、Log4Qt簡介 Log4Qt是使用Trolltech Qt Framework的Apache Software Foundation Log4j包的C 端口。它旨在供開源和商業Qt項目使用。所以 Log4Qt 是Apa…

Java零拷貝技術實戰

文章目錄 引入傳統IO內存映射mmap文件描述符sendFile測試總結 引入 為什么要使用零拷貝技術&#xff1f; 傳統寫入數據需要4次拷貝&#xff0c;如下圖&#xff1a; 傳統IO import java.io.*; import java.net.Socket;public class TranditionIOClient {private static fina…