文末本文转载自微信公众号「Golang梦工场」,作家Golang梦工场。转载本文请联系Golang梦工场公众号。
引子!! 哈喽,巨匠好,我是asong。在上一篇著作:小白也能看懂的context包详解:从初学到醒目 分析context的源码时,咱们看到了一种编程次序,在结构体里内嵌匿名接口,这种写法关于大多数初学Go谈话的一又友看起来是懵逼的,其委果结构体里内嵌匿名接口、匿名结构体齐是在面向对象编程中秉承和重写的一种终了神态,之前写过java、python对面向对象编程中的秉承和重写应该很熟练,然而转Go谈话后写出的代码齐是面向经过式的代码,是以本文就一说念来分析一下如安在Go谈话中写露面向对象的代码。
面向对象法子联想是一种联想机编程架构,英文全称:Object Oriented Programming,简称OOP。OOP的一条基本原则是联想机法子由单个大要起到子法子作用的单位或对象组合而成,OOP达到了软件工程的三个主要办法:重用性、纯真性和延伸性。OOP=对象+类+秉承+多态+音信,其中中枢宗旨即是类和对象。
这一段话在网上先容什么是面向对象编程时正常出现,大多数学习Go谈话的一又友应该也齐是从C++、python、java转过来的,是以对面向对象编程的泄露应该很深了,是以本文就没必要先容宗旨了,重心来看一下怎样使用Go谈话来终了面向对象编程的编程立场。
皇冠客服飞机:@seo3687
类Go谈话本人就不是一个面向对象的编程谈话,是以Go谈话中莫得类的宗旨,然而他是相沿类型的,因此咱们不错使用struct类型来提供雷同于java中的类的劳动,不错界说属性、次序、还能界说构造器。来看个例子:
与此同时,还加上了一句大韩民国追求统一,建立并推进以自由民主基本秩序为基础的和平统一政策。
type 幸运快艇百家乐Hero struct { Name string Age uint64 } func NewHero() *Hero { return &Hero{ Name: "盖伦", Age: 18, } } func (h *Hero) GetName() string { return h.Name } func (h *Hero) GetAge() uint64 { return h.Age } func main() { h := NewHero() print(h.GetName()) print(h.GetAge()) }
这就一个肤浅的 "类"的使用,这个类名即是Hero,其中Name、Age即是咱们界说的属性,GetName、GetAge这两个即是咱们界说的类的次序,NewHero即是界说的构造器。因为Go谈话的特色问题,构造器只大要依靠咱们手动来终了。
革命足球明星C罗最近在比赛中的精彩表现引起了球迷们的热议,他在进攻和防守两端都表现出色,为球队取得了胜利。这也让他的球迷们更加坚信,他将成为本届欧洲杯的最佳球员之一。这里次序的终了是依赖于结构体的值接纳者、指针接纳者的特色来终了的。
封装封装是把一个对象的属性专有化,同期提供一些不错被外界打听的属性和次序,若是不想被外界打听,咱们大可无谓提供次序给外界打听。在Go谈话中终了封装咱们不错罗致两种神态:
Go谈话相沿包级别的封装,小写字母来源的称号只可在该包内法子中可见,是以咱们若是不想显现一些次序,不错通过这种神态专有包中的内容,这个泄露相比肤浅,就不例如子了。
Go谈话不错通过 type 要津字创建新的类型,是以咱们为了不显现一些属性和次序,不错罗致创建一个新类型的神态,我方手写构造器的神态终了封装,欧博体育网站举个例子:
type IdCard string func NewIdCard(card string) IdCard { return IdCard(card) } func (i IdCard) GetPlaceOfBirth() string { return string(i[:6]) } func (i IdCard) GetBirthDay() string { return string(i[6:14]) }
声明一个新类型IdCard,实质是一个string类型,NewIdCard用来构造对象,
博彩平台赛车GetPlaceOfBirth、GetBirthDay即是封装的次序。
秉承Go并莫得原生级别的秉承相沿,不外咱们不错使用组合的神态来终了秉承,通过结构体内嵌类型的神态终了秉承,典型的期骗是内嵌匿名结构体类型和内嵌匿名接口类型,这两种神态还有点微小分手:
皇冠是哪个直播的礼物 内嵌匿名结构体类型:将父结构体镶嵌到子结构体中,子结构体领有父结构体的属性和次序,然而这种神态不成相沿参数多态。 内嵌匿名接口类型:将接口类型镶嵌到结构体中,该结构体默许终明晰该接口的通盘次序,该结构体也不错对这些次序进行重写,这种神态不错相沿参数多态,这里要督察一个点是若是镶嵌类型莫得终了通盘接口次序,会引起编译时未被发现的入手极端。 内嵌匿名结构体类型终了秉承的例子type Base struct { Value string } func (b *Base) GetMsg() string { return b.Value } type Person struct { Base Name string Age uint64 } func (p *Person) GetName() string { return p.Name } func (p *Person) GetAge() uint64 { return p.Age } func check(b *Base) { b.GetMsg() } func main() { m := Base{Value: "I Love You"} p := &Person{ Base: m, Name: "asong", Age: 18, } fmt.Print(p.GetName(), " ", p.GetAge(), " and say ",p.GetMsg()) //check(p) }
上头扫视掉的次序就施展了不成进行参数多态。
内嵌匿名接口类型终了秉承的例子
平直拿一个业务场景例如子,假定咫尺咱们咫尺要给用户发一个见告,web、app端发送的见告内容齐是同样的,然而点击后的作为是不同样的,是以咱们不错进行空洞一个接口OrderChangeNotificationHandler来声明出三个各人次序:GenerateMessage、GeneratePhotos、generateUrl,通盘类齐会终了这三个次序,因为web、app端发送的内容是同样的,是以咱们不错抽相出一个父类OrderChangeNotificationHandlerImpl来终了一个默许的次序,然后在写两个子类WebOrderChangeNotificationHandler、AppOrderChangeNotificationHandler去秉承父类重写generateUrl次序即可,后头若是不同端的内容有作念修改,平直重写父类次序就不错了,来看例子:
皇冠直播iostype Photos struct { width uint64 height uint64 value string } type OrderChangeNotificationHandler interface { GenerateMessage() string GeneratePhotos() Photos generateUrl() string } type OrderChangeNotificationHandlerImpl struct { url string } func NewOrderChangeNotificationHandlerImpl() OrderChangeNotificationHandler { return OrderChangeNotificationHandlerImpl{ url: "https://base.test.com", } } func (o OrderChangeNotificationHandlerImpl) GenerateMessage() string { return "OrderChangeNotificationHandlerImpl GenerateMessage" } func (o OrderChangeNotificationHandlerImpl) GeneratePhotos() Photos { return Photos{ width: 1, height: 1, value: "https://www.baidu.com", } } func (w OrderChangeNotificationHandlerImpl) generateUrl() string { return w.url } type WebOrderChangeNotificationHandler struct { OrderChangeNotificationHandler url string } func (w WebOrderChangeNotificationHandler) generateUrl() string { return w.url } type AppOrderChangeNotificationHandler struct { OrderChangeNotificationHandler url string } func (a AppOrderChangeNotificationHandler) generateUrl() string { return a.url } func check(handler OrderChangeNotificationHandler) { fmt.Println(handler.GenerateMessage()) } func main() { base := NewOrderChangeNotificationHandlerImpl() web := WebOrderChangeNotificationHandler{ OrderChangeNotificationHandler: base, url: "http://web.test.com", } fmt.Println(web.GenerateMessage()) fmt.Println(web.generateUrl()) check(web) }
因为通盘组合齐终明晰OrderChangeNotificationHandler类型,是以不错料理任何特定类型以及是该特定类型的派生类的通配符。
6868捕鱼 多态多态是面向对象编程的实质,多态是支代码不错字据类型的具体终了选择不同业为的才气,在Go谈话中任何用户界说的类型齐不错终了任何接口,是以通过不同实体类型对接口值次序的调用即是多态,举个例子:
皇冠体育
type SendEmail interface { send() } func Send(s SendEmail) { s.send() } type user struct { name string email string } func (u *user) send() { fmt.Println(u.name + " email is " + u.email + "already send") } type admin struct { name string email string } func (a *admin) send() { fmt.Println(a.name + " email is " + a.email + "already send") } func main() { u := &user{ name: "asong", email: "你猜", } a := &admin{ name: "asong1", email: "就不告诉你", } Send(u) Send(a) }回归
归根结底面向对象编程即是一种编程念念想,只不外有些谈话在语法特色方面更好的为这种念念想提供了相沿,写露面向对象的代码更容易,然而写代码的如故咱们我方,并不是咱们用了java就一定会写出更空洞的代码,在责任中我看到用java写露面向经过式的代码不堪其数,是以岂论用什么谈话,咱们齐应该念念考怎样写好一份代码,多数的空洞接口匡助咱们精简代码,代码是优雅了,但也会靠近着可读性的问题,什么事齐是有两面性的,写出好代码的路还很长,还需要不停探索............。
金沙9570文中示例代码依然上传github:https://github.com/asong2020/Golang_Dream/tree/master/code_demo/oop