文章目录

  • Struct定义
  • struct 方法
  • 工厂模式
  • 面向对象三大特性
    • 封装
    • 继承
    • 接口
    • 多态
  1. Golang支持面向对象编程,但是和传统面向对象有区别,并不是纯粹面向对象的语言,只能说Golang支持面向对象编程特性
  2. Golang没有类,通过结构体struct 来实现OOP,非常简洁。

Struct定义

  1. Struct字段声明语法同变量,创建一个结构体后如果没有为字段赋值 则字段取值为默认值
  2. 结构体可以进行type 重新定义,Golang默认是新类型
  3. 结构体是用户单独定义的类型,和其他类型转换时需要有完全相同的字段(名字、个数、类型)
  4. struct 每个字段 都可以写上一个tag,该tag 可以通过反射机制获取
  5. 结构体所有字段在内存中是连续的

示例代码

//声明一个结构体
type Cat struct{Name stringAge intColor stringHobby string
}
func test01(){//创建结构体并赋值1var cat1 Catcat1.Name = "小白"cat1.Age = 10cat1.Color = "白色"cat1.Hobby = "吃 鱼"var cat2 Catfmt.Println(cat1,cat2)//{小白 10 白色 吃 鱼} { 0  }//创建结构体并赋值2c3 := Cat{"小黑",20,"黑色","shuijiao"}//创建结构体并赋值3var c4 *Cat = new(Cat)(*c4).Name = "小花" //通过索引访问值 再访问属性c4.Age = 10 //也可以直接通过索引访问属性(goLang做了优化)//创建结构体并赋值4var c5 *Cat  = &Cat{}c5.Name = "c5"fmt.Println(cat1,cat2,c3,c4,c5)c6 := c3c6.Name ="c6"//赋值后会直接克隆一个变量给C6,修改c6的值 c3 不受影响//{小黑 20 黑色 shuijiao} {c6 20 黑色 shuijiao}fmt.Println(c3,c6)//创建结构体变量时直接指定字段值var c7 = Cat{Name:"小绿",Age:40,}fmt.Println(c7) }
type Point struct{x inty int
}
type Rect struct{leftUp, rightDown Point
}
type Rect2 struct{leftUp, rightDown *Point
}func test02(){//结构体所有字段在内存中是连续的r1 := Rect{Point{1,2} , Point{3,4}}fmt.Printf("r1.rd.x地址= %p r1.rd.y地址= %p r1.lu.x地址= %p r1.lu.y地址= %p  \n",&r1.rightDown.x,&r1.rightDown.y,&r1.leftUp.x,&r1.leftUp.y)// fmt.Printf("r1.rd.x地址= %p r1.rd.y地址= %p r1.lu.x地址= %p r1.lu.y地址= %p  \n",//&r1.rightDown.x,&r1.rightDown.y,&r1.leftUp.x,&r1.leftUp.y)r2 := Rect2{&Point{1,2} , &Point{3,4}}fmt.Printf("r2.rd.x地址= %p r2.rd.y地址= %p r2.lu.x地址= %p r2.lu.y地址= %p  \n",&r2.rightDown.x,&r2.rightDown.y,&r2.leftUp.x,&r2.leftUp.y)//结构体是用户单独定义的类型,和其他类型转换时需要有完全相同的字段(名字、个数、类型)type A struct{Num int}type B struct{Num int}var a Avar b Ba = A(b)a.Num =10fmt.Println(a,b)//结构体进行type 重新定义,Golang默认是新类型,type AA Avar aa AA//var a A = aa 报错需要强转var a3 A = A(aa)fmt.Println(aa,a3)//struct 每个字段 都可以写上一个tag,该tag 可以通过反射机制获取//常见的场景就是 序列化和反序列化type Monster struct {Name string `json:"name"`Age int `json:age`}m1 := Monster{"牛魔王",300}jsonstr ,err := json.marshal(m1)if err != nil {fmt.Println("json 字符串处理错误")}fmt.Println("json 字符串=",jsonstr)
}

struct 方法

struct 方法声明语法 表示 A结构体有一个test 方法 (a A)标识这个方式是和 A类型绑定的

func( a A)test(){}
func( a A)test2(参数列表)(返回值列表){方法体return 返回值
}

注意点

  1. 在通过一个结构变量去调用方法时,调用机制和函数相同,只不过调用结构体方法时,结构体变量也会作为一个参数传递到方法中。
  2. Golang中的方法是指定在数据类型上的,因此所有自定义类型都可以有方法,包括 struct、int 、float32
  3. 如果一个类型实现了 String() 这个方法,那么 fmt.Println 默认会调用变量的这个方法作为结果进行输出
  4. 通过变量去调用方法时,其(参数传递)机制和函数一样,不一样的地方是变量本身也会作为参数传递给该方法(如果变量是值类型则进行值拷贝,如果是引用类型则进行地质拷贝,如果希望在方法中修改结构体的值可以使用指针来传递)。
  5. 方法的访问范围控制和函数一样,方法名首字母小写只在本包访问,大写可以在包外访问。

示例代码

//定义结构体
type Person struct{Name string
}
//定义方法
func (p Person) speak(){fmt.Println(p.Name,"是一个好人")
}
func test03(){p := Person{"zhangsan"}p.speak()
}

工厂模式

工厂模式用来通过指定的方法来创建(只在包内可用的/首字母小写的结构体)实例。
同时如果结构体的属性 首字母小写也可以通过方法类获取(类似于java中的set/get 方法)
实例代码

func test04(){var stu = mode.NewStudent("tom",12.0)fmt.Println(*stu)fmt.Println(stu.Name,stu.GetScore())
}
package modeltype student struct{Name stringscore float64
}
//通过工厂方法获取 隐藏结构的实例
func NewStudent(n string,s float64) *student{return &student{Name:n,score:s}
}
//通过方法或去被封装的属性
func( stu *student) GetScore () float64{return stu.score
}

面向对象三大特性

Golang也有面向对象编程的三大特性,只不过实现方式和其他OOP语言不同

封装

将抽象出来的字段封装在一起
好处:隐藏实现细节 同时借助统一访问方法,可以对数据进行验证,保证数据合理性
实现方式

  1. 将结构体、字段首字母小写(类似java private)
  2. 为封装的结构体提供工厂模式函数,首字母大写,类似一个构造函数
  3. 为结构体提供首字母大写的Set/Get 方法 用于属性读写
    示例代码
func test05(){var per = mode.NewPerson("TOM")per.SetAge(50)per.SetSal(10000.0)fmt.Println(per)fmt.Println(per.GetAge(),per.GetSal(),per.Name)}
package model
import ("fmt"
)
type person struct{Name stringage intsal float64
}
// 封装工厂方法 创建结构体实例
func NewPerson(name string) *person{return &person{Name:name,}
}
func (p *person)SetAge(age int){if age>0 && age<150{p.age = age } else{fmt.Println("年龄不在合法范围内")}}func (p *person)SetSal(sal float64){if sal>3000 && sal<30000{p.sal = sal } else{fmt.Println("薪资不在合法范围内")}
}
func (p *person)GetAge() int {fmt.Println("====>",p.age)return p.age
}func (p *person)GetSal() float64 {fmt.Println("====>",p.sal)return p.sal
}

继承

继承可以解决代码的复用,当多个结构体存在相同的字段和方法时,可以抽象出一个结构体包含公有的属性和方法。其他结构体不用定义这些属性和方法,只需要嵌套这个结构体即可。
就是说如果一个结构体嵌套了另外一个匿名结构体,那么这个结构体可以直接访问匿名结构体的方法和字段,如此就实现了继承。
基本语法形式

type Goods struct{Name stringPrice int
}
type Book struct{Goods //嵌套匿名结构体Writer string
}

示例代码

func test06(){pu := &Pupil{}pu.Student.Name = "TOM"pu.Student.Age =12pu.Age=13//对继承的字段可以简化访问pu.testing();pu.Student.ShowInfo()pu.ShowInfo()//方法简化访问//声明结构体时直接为嵌套结构体赋值pu2 := &Pupil{Student{Name: "Jack",Age:19,Score:100,},}pu2.ShowInfo()
}
//定义学生类
type Student struct{Name stringAge intScore int
}
//显示学生信息
func (stu *Student)ShowInfo(){fmt.Println(stu)
}
func (stu *Student) SetCore(score int){stu.Score = score
}
//定义小学生类
type Pupil struct{Student//嵌入 学生结构体
}
func (p *Pupil) testing(){fmt.Println("小学生正在考试...")
}

注意点

  1. 结构体可以使用匿名结构体的所有字段和方法,无论首字母大写还是小写
  2. 结构体访问匿名结构体方法和属性可以简化,简化访问时访问逻辑:如果当前结构体有访问属性/方法则直接调用本结构体的该属性/方法,如果当前结构体没有该属性/方法,则到嵌套的匿名结构体中找该属性/方法,找到就调用,如果找不到就报错。
  3. 当结构体和嵌套结构体有相同的属性或方法时,编译器采用就近访问原则。如果想调用匿名结构体中的属性/方法这个时候就必须 通过匿名结构体的名字进行调用(不能进行简化调用)
  4. 如果一个结构体嵌套了多个结构体,且多个嵌套结构体包含相同的属性/方法,那么在调用时就必须指明匿名结构体的名字。否则编译器报错
  5. 如果一个结构体嵌套了一个有名字的结构体,那么二者是组合关系,这个时候访问组合结构体的属性/方法时必须带上 结构体的名字
  6. 嵌套结构体变量后,可以在创建结构体变量时直接为嵌套结构体赋值。
  7. 如果一个结构体中嵌套了基本数据类型如int,访问方式 A.int=12, 如果要有多个int字段必须制定名字

多重继承
如果一个struct 嵌套了多个匿名结构体,那么它可以访问所有结构体的字段和方法,这就是Golang的多重继承
*如果嵌套的多个结构体中包含相同的属性/方法,那么在调用方法时必须明确嵌套结构体的名字

接口

interface 类型可以定义一组方法,但是不需要实现,并且interface 不能包含任何变量,在具体类型中根据实际情况实现这些方法。

type 接口名 interface{method1()method2()
}

示例程序

type Gun interface{Fire()
}
type Gun51 struct{}
func(g Gun51) Fire(){fmt.Println("Gun51连续发射7mm子弹...")
}
type GunRPG struct{}
func(g GunRPG) Fire(){fmt.Println("RPC发射火箭弹...")
}
func test07(){var g51 Gun51var rpg GunRPGvar gun Gun = g51gun.Fire();gun = rpggun.Fire()
}

注意点

  1. 接口里所有的方法都没有方法体,体现了程序 高内聚低耦合的思想
  2. Golang 中不显式的实现接口,只要一个变量中包含接口声明的所有方法,就认为这个变量实现了这个接口。
  3. 接口本身不创建实例,但是可以指向一个实现了该接口的实例
  4. 一个自定义类型只有实现了某个接口,才可以将该类型变量赋值给这个接口。
  5. 任何自定义类型都可以实现接口 不一定是结构体,且一个变量可以实现多个接口
  6. 接口A可以继承多个其他接口B、C,这个时候如果变量实现A接口也必须同时实现B和C接口。如果接口(包括继承的接口)中包含重复的方法,那么编译器报错
  7. interface 默认是一个指针类型,如果没有初始化默认输出nil
  8. 空接口 没有任何方法,所有类型都实现了空接口,即所有类型都可以赋值给空接口

继承和接口比较
继承主要解决代码的复用性和可维护性。强调共性复用。
接口主要是设计规范,让其他类型遵守规范 。强调共性能力 各自实现。
接口一定程度上实现代码解耦

多态

变量具有多种形态,Golang中多态通过接口实现。按照同一个接口在不同变量中做不同实现,这时接口就呈现多种不同状态。(见接口示例)
一般通过方法参数体现多态

类型断言
如何将一个接口变量赋值给自定义类型变量?需要先确定变量的类型,即类型断言
示例代码

func test08(){var x interface{}var b2 int = 1x = b2// 将x 转换为int  y, ok := x.(int); if ok {fmt.Printf("转换成功 y的类型是%T 值是=%v \n",y,y);}else{fmt.Println("转换失败")}fmt.Println("x.(int)==>",x.(int))//fmt.Println("x.(type)==>",x.(type)) 只能在switch 中使用 这里使用报错//调用断言方法TypeJudge(b2)
}func TypeJudge(items... interface{}){for index,x := range items{switch x.(type){case bool :fmt.Printf("第%v个参数是 bool 类型,值是 %v \n",index,x)case float32:fmt.Printf("第%v个参数是 float32 类型,值是 %v \n",index,x)case float64:fmt.Printf("第%v个参数是 float64 类型,值是 %v \n",index,x)case int,int32,int64:fmt.Printf("第%v个参数是 int 类型,值是 %v \n",index,x)case string:fmt.Printf("第%v个参数是 string 类型,值是 %v \n",index,x)default:fmt.Printf("第%v个参数 类型不确定,值是 %v \n",index,x)}}
}

07 面向对象编程-结构、封装、继承、多态、接口相关推荐

  1. 第九课(面向对象):封装 继承 多态

    一.面向对象概念:根据模板(创建一个类)并实例化 这个思路就叫面向对象 二.使用面向对象编程好处: 可以重复使用(实例化类) 容易修改(只用修改类的模板) 三.面向对象的特点: 封装 继承 多态 类名 ...

  2. -1-2 java 面向对象基本概念 封装继承多态 变量 this super static 静态变量 匿名对象 值传递 初始化过程 代码块 final关键字 抽象类 接口

    java是纯粹的面向对象的语言 也就是万事万物皆是对象 程序是对象的集合,他们通过发送消息来相互通信 每个对象都有自己的由其他的对象所构建的存储,也就是对象可以包含对象 每个对象都有它的类型  也就是 ...

  3. 【小白学java】java的面向对象设计:封装+继承+抽象类+接口(day06)

    课程链接:共六天 第一天:开发环境:初识java,搭建环境 第二天:语言基础:关键字.变量.常量.运算符 第三天:数据结构:基本类型.包装类型.引用类型(数组和对象) 第四天:流程控制:分支判断.循环 ...

  4. Java面向对象三大特性(封装继承多态)解释及案例

    文章目录 包 包基本语法 命名规则 命名规范 导入包实例 访问修饰符 面向对象编程-封装 面向对象编程-继承 super关键词 super和this的比较 方法重写/覆盖 (override) 注意事 ...

  5. (十)Core Java 面向对象(封装,继承,多态,接口) -02 (96)

     目录 :        24 ). 面向对象(聚集关系) 25 ). 面向对象(子父类中变量的特点) 26 ). 面向对象(子父类中函数的特点-覆盖) 27 ).  面向对象(子父类中构造函数的特点 ...

  6. 深入理解Java面向对象三大特性 封装 继承 多态

    1.封装 封装的定义: 首先是抽象,把事物抽象成一个类,其次才是封装,将事物拥有的属性和动作隐藏起来,只保留特定的方法与外界联系 为什么需要封装: 封装符合面向对象设计原则的第一条:单一性原则,一个类 ...

  7. c语言编程 菲薄拉,C语言设计模式-封装-继承-多态

    快过年了,手头的工作慢慢也就少了,所以,研究技术的时间就多了很多时间,前些天在CSDN一博客看到有大牛在讨论C的设计模式,正好看到了,我也有兴趣转发,修改,研究一下. 记得读大学的时候,老师就告诉我们 ...

  8. Day55-每日一道Java面试题-Java 面向对象编程三大特性: 封装 继承 多态

    Java 面向对象编程三大特性: 封装 继承 多态 封装 封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果属性不想被外界访问,我们大可不必提供方法给外界访问.但是如果一个类没有 ...

  9. Java基础【之】面向对象编程(封装、继承(extends、方法重写、super)、多态(动态绑定、重载/重写)、代码实现)

    Java基础[之]面向对象编程(封装.继承.多态.代码实现) 1.封装 2.继承 2.1.extends 2.2.方法重写 2.3.super 3.多态 3.1.对象的多态.方法的多态 3.2.动态绑 ...

最新文章

  1. golang make()内置函数
  2. 微信小程序上传图片时provisional headers are shown显示我的错误解决方案
  3. 解决intellij IEDA mapper.xml文件警告以及could not autowire的错误提示
  4. ORACLE SQL:经典查询练手第二篇
  5. Java知多少(96)绘图之设置字型和颜色
  6. 动态绑定 datagridview
  7. MapReduce基础
  8. 自定义的plot函数参数date坐标模型[x,y]的使用建议
  9. 网页制作 css样式,网页设计与制作-CSS样式.ppt
  10. Spring IOC学习心得之源码级分析ContextLoaderListener的作用(IOC容器初始化入口)
  11. 成功编译无错MAC OpenJDK8:Terminating app due to uncaught exception ‘NSInternalInconsistencyException‘
  12. Visio2010的下载
  13. moment.js获取一周的第一天
  14. javafx实现简单的计时器
  15. matlab2017百度百科,沸石粉里的吸蓝量是什么意思
  16. red5 1.0.7 集成tomcat 并且 进行整合 官方例子oflaDemo
  17. 看理想:3万辆交付意味着什么?
  18. 移动互联网时代的失意者
  19. 2015年1月9日XX大学XX学院考试题
  20. 三.基础部分+asp网站搭建

热门文章

  1. GBA程序开发入门1
  2. 手机cpu性能天梯图2022 手机cpu性能排行2022 手机cpu哪个好
  3. 毕业论文用什么流程图软件比较好?
  4. java swing(GUI) MySQL实现的学生选课签到考勤系统源码开发教程
  5. 柳廷顯 任汝所用 月亭
  6. 从5毛到3块,涪陵榨菜是怎样让我们吃不起的?
  7. html5图片和两行文字垂直居中显示,何如让文字跟图片垂直居中对齐
  8. 后台管理系统 权限管理
  9. MT6735 刷机时:brom error:s ft download fail 4008
  10. react按钮倒计时效果(发送验证码按钮)