Golang - 面对"对象"
Golang - 面对"对象"
1. 简介
- go语言对于面向对象的设计非常简洁而优雅
- 没有封装、继承、多态这些概念,但同样通过别的方式实现这些特性
- 封装:通过方法实现
- 继承:通过匿名字段实现
- 多态:通过接口实现
2. 匿名字段
go支持只提供类型而不写字段名的方式,也就是匿名字段,也称为嵌入字段
//package 声明开头表示代码所属包
package main
import "fmt"
//定义人的结构体
type Person struct {
name string
sex string
age int
}
//学生
type Student struct {
//匿名字段
//默认Student包含了Person所有字段
Person
id int
addr string
}
func main() {
s2 := Student{Person:Person{"约汉","female",10},id:2}
fmt.Println(s2)
}
//{{约汉 female 10} 2 }
同名字段的情况
//package 声明开头表示代码所属包
package main
import "fmt"
//定义人的结构体
type Person struct {
name string
sex string
age int
}
//学生
type Student struct {
//匿名字段
//默认Student包含了Person所有字段
Person
id int
addr string
//同名字段
name string
}
func main() {
var s Student
//就近赋值
s.name = "约汉"
fmt.Println(s)
//若给外面赋值
s.Person.name = "接客"
fmt.Println(s)
}
//{{ 0} 0 约汉}
//{{接客 0} 0 约汉}
所有的内置类型和自定义类型都是可以作为匿名字段去使用
package main
import "fmt"
//定义人的结构体
type Person struct {
name string
sex string
age int
}
//自定义类型
type mystr string
//学生
type Student struct {
//匿名字段
//默认Student包含了Person所有字段
Person
//内置
int
mystr
}
func main() {
//初始化
s1 := Student{Person{"约汉","male",18},1,"bj"}
fmt.Println(s1)
fmt.Println(s1.name)
}
指针类型匿名字段
//package 声明开头表示代码所属包
package main
import "fmt"
//定义人的结构体
type Person struct {
name string
sex string
age int
}
//学生
type Student struct {
//匿名字段
//默认Student包含了Person所有字段
*Person
//内置
id int
addr string
}
func main() {
s1 := Student{&Person{"约汉","male",18},1,"bj"}
fmt.Println(s1)
fmt.Println(s1.name)
}
//{0xc0420661e0 1 bj}
//约汉
3. 方法
4. 包和封装
5. 接口
- 在面向对象编程中,一个对象其实也就是一个简单的值或者一个变量,在这个对象中会包含一些函数
- 这种带有接收者的函数,我们称为方法,本质上,一个方法则是一个和特殊类型关联的函数
- 方法的语法如下
- func (接收参数名 接收类型) 方法名(参数列表)(返回值)
- 可以给任意自定义类型(包括内置类型,但不包括指针类型)添加相应的方法
- 接收类型可以是指针或非指针类型
- 为类型添加方法(为基础类型添加方法和为结构体类型添加方法)
基础类型
//package 声明开头表示代码所属包
package main import "fmt" //任务:定义方法实现2个数相加 type MyInt int //传统定义方式,面向过程
func Add(a, b MyInt) MyInt {
return a + b
} //面向对象
func (a MyInt) Add(b MyInt) MyInt {
return a + b
} func main() {
var a MyInt = 1
var b MyInt = 1
fmt.Println("Add(a,b)=", Add(a, b))
//调用面向对象的方法
fmt.Println("a.Add(b)=",a.Add(b))
} //Add(a,b)= 2
//a.Add(b)= 2
结构体类型
//package 声明开头表示代码所属包
package main import "fmt" type Person struct {
name string
sex string
age int
} //为Person添加方法
func (p Person) PrintInfo() {
fmt.Println(p.name, p.sex, p.age)
} func main() {
p := Person{"接客", "male", 18}
p.PrintInfo()
}
值语义和引用语义
//package 声明开头表示代码所属包
package main import "fmt" type Person struct {
name string
sex string
age int
} //设置指针作为接收者的方法,引用语义
func (p *Person) SetInfoPointer() {
(*p).name = "接客"
p.sex = "female"
p.age = 22
} //值作为接收者,值语义
func (p Person) SetInfoValue() {
p.name = "约汉"
p.sex = "male"
p.age = 20
} func main() {
//指针作为接收者的效果
p1 := Person{"撸死", "male", 19}
fmt.Println("函数调用前=", p1)
(&p1).SetInfoPointer()
fmt.Println("函数调用后=", p1)
fmt.Println("================寂寞的分割线=================") //值作为接收者的效果
p2 := Person{"约汉", "male", 18}
fmt.Println("函数调用前=", p2)
p2.SetInfoValue()
fmt.Println("函数调用后=", p2)
} //函数调用前= {撸死 male 19}
//函数调用后= {接客 female 22}
//================寂寞的分割线=================
//函数调用前= {约汉 male 18}
//函数调用后= {约汉 male 18}
方法的继承
package main import "fmt" type Person struct {
name string
sex string
age int
} //为Person定义方法
func (p *Person) PrintInfo() {
fmt.Printf("%s,%s,%d\n",p.name,p.sex,p.age) } type Student struct {
Person
id int
addr string
} func main() {
p :=Person{"接客","male",18}
p.PrintInfo()
//学生也去调,方法继承
s := Student{Person{"接客","male",18},2,"bj"}
s.PrintInfo()
}
方法的重写
package main import "fmt" type Person struct {
name string
sex string
age int
} //为Person定义方法
func (p *Person) PrintInfo() {
fmt.Printf("%s,%s,%d\n", p.name, p.sex, p.age)
} type Student struct {
Person
id int
addr string
} //Student定义方法,实际上就相当于方法重写
func (s *Student) PrintInfo() {
fmt.Printf("Student:%s,%s,%d\n", s.name, s.sex, s.age)
} func main() {
p := Person{"接客", "male", 18}
p.PrintInfo()
//学生也去调,方法继承
s := Student{Person{"接客", "male", 18}, 2, "bj"}
s.PrintInfo()
//显式调用
s.Person.PrintInfo()
}
方法值和方法表达式
package main import "fmt" type Person struct {
name string
sex string
age int
} func (p *Person) PrintInfoPointer() {
//%p是地址,%v是值
fmt.Printf("%p,%v\n", p, p)
} func main() {
p := Person{"接客", "male", 18}
//传统的调用方法的方式
p.PrintInfoPointer()
//使用go方法值特性调用
pFunc1 := p.PrintInfoPointer
pFunc1()
//使用go方法表达式调用
pFunc2 := (*Person).PrintInfoPointer
pFunc2(&p)
}
练习:创建属性的getter和setter方法并进行调用
package main
import "fmt"
type Dog struct {
name string
//1公 0母
sex int
}
//封装dog的方法
//setter
func (d *Dog) SetName(name string) {
d.name = name
}
//getter
func (d *Dog) GetName() string {
return d.name
}
//咬人
func (d *Dog) bite() {
fmt.Printf("让本汪%s 来给你上课...", d.name)
}
func main() {
d := Dog{"二哈", 1}
d.bite()
}
4. 包和封装
- 方法首字母大写:public
- 方法首字母小写:private
- 为结构体定义的方法必须放在同一个包内,可以是不同的文件
- 上面代码复制到test包中,在test02包中进行调用,需要调用的方法名首字母大写
5. 接口
go语言中,接口(interface)是一个自定义类型,描述了一系列方法的集合
接口不能被实例化
接口定义语法如下
type 接口名 interface{}
PS:接口命名习惯以er结尾
接口定义与实现
package main import "fmt" //定义人的接口
type Humaner interface {
//说话
Say()
} //学生结构体
type Student struct {
name string
score int
} //Student实现Say()方法
func (s *Student) Say() {
fmt.Printf("Student[%s,%d] 瞌睡不断\n", s.name, s.score)
} type Teacher struct {
name string
group string
} //老师实现接口
func (t *Teacher) Say() {
fmt.Printf("Teacher[%s,%s] 毁人不倦\n", t.name, t.group)
} //自定义类型
type MyStr string //自定义类型实现方法
func (str MyStr) Say() {
fmt.Printf("MyStr[%s] 同志醒醒,还有个bug\n", str)
} func WhoSay(i Humaner) {
i.Say()
} func main() {
s := &Student{"约汉", 88}
t := &Teacher{"撸死", "Go语言"}
var tmp MyStr = "接客" s.Say()
t.Say()
tmp.Say() //go的多态,调用同一个接口,不同表现
WhoSay(s)
WhoSay(t)
WhoSay(tmp) //make()创建
x := make([]Humaner, 3)
x[0], x[1], x[2] = s, t, tmp
for _, value := range x {
value.Say()
}
}
接口继承
package main import "fmt" //定义人的接口
type Humaner interface {
//说话
Say()
}
type Personer interface {
//等价于写了Say()
Humaner
Sing(lyrics string)
} //学生结构体
type Student struct {
name string
score int
} //Student实现Say()方法
func (s *Student) Say() {
fmt.Printf("Student[%s,%d] 瞌睡不断\n", s.name, s.score)
} func (s *Student) Sing(lyrics string) {
fmt.Printf("Student sing[%s]!!\n", lyrics)
} func main() {
s := &Student{"约汉", 88}
var p Personer
p = s
p.Say()
p.Sing("互撸娃")
}
空接口:空interface{}不包含任何方法,空接客可以存储任意类型的值
类型查询
comma-ok断言
package main import "fmt" //空接口
type Element interface{} type Person struct {
name string
age int
} func main() {
//切片
list := make([]Element, 3)
//int
list[0] = 1
list[1] = "Hello"
list[2] = Person{"luhan", 18}
//遍历
for index, element := range list {
//类型断言:value ,ok = element.(T)
//value 是变量的值,ok是返回的布尔值,element是接口变量,T是断言类型
if value, ok := element.(int); ok {
fmt.Printf("list[%d]是int类型,值是%d\n", index, value)
} else if value, ok := element.(int); ok {
fmt.Printf("list[%d]是int类型,值是%d\n", index, value)
} else if value, ok := element.(Person); ok {
fmt.Printf("list[%d]是Person类型,值是[%s,%d]\n",
index, value.name, value.age)
} else {
fmt.Printf("list[%d]是其他类型\n", index)
}
}
}
switch测试
package main import "fmt" //空接口
type Element interface{} type Person struct {
name string
age int
} func main() {
//切片
list := make([]Element, 3)
//int
list[0] = 1
list[1] = "Hello"
list[2] = Person{"luhan", 18}
//遍历
for index, element := range list {
switch value := element.(type) {
case int:
fmt.Printf("list[%d]是int类型,值是%d\n", index, value)
case string:
fmt.Printf("list[%d]是string类型,值是%s\n", index, value)
default:
fmt.Printf("list[%d]是其他类型\n", index)
}
}
}
Golang - 面对"对象"的更多相关文章
- golang面对对象
- 跟着百度学PHP[4]OOP面对对象编程-7-OOP的一些关键子讲解
面对对象常用的一些关键子:http://www.cnblogs.com/xishaonian/p/6146794.html排版不是很好望见谅. THE END
- python面对对象编程----2:__init__
面对对象编程估计我们最早接触到的就是__init__了,也就是实例的初始化处理过程: 1:来看看最基础的__init__ class Card(object): #抽象类Card,并不用于实例化 de ...
- Javascript面对对象. 第一篇
Javascript,有两个种开发模式: 1.函数式(过程化)2.面对对象(oop),面对对象语言有一个标志,就是类,而通过类可以创建任何多个属性和方法,而Ecmascript没有类的概念,因此它的对 ...
- Java入门——(2)面对对象(上)
关键词:面对对象.类..构造方法.this.static.内部类 一.面对对象的概念:把解决的问题安装一定规则划分为多个独立的对象,然后通过调用对象的方法来解决问题.其特点可概括为封装性.继承 ...
- Day-8: 面对对象编程
面对过程的程序设计方法意在将函数分成子函数,再依次调用这些函数来解决问题. 而面对对象的程序设计方法,来源于自然界,类是实例的抽象,实例是类的具体.自定义出来的对象是类,而所有的数据都可以看成是对象, ...
- java基础--面对对象
面对对象--概述 什么是对象? +---->对象可以泛指一切现实中存着的事物 +---->类是对象的抽象集合 什么是面对对象? +--->万物皆对象,面对对象实际就是人与万物接触== ...
- Python进阶_面对对象&面对过程
这节主要讲面对对象与面对过程两种编程思想的主要区别. 一. 简单对比 面向过程是一种基础的方法,它考虑的是实际的实现步骤,一般情况下,面向过程是自顶向下逐步求精,其最重要的是模块化的思想方法. 面向对 ...
- python面对对象(不全解)
面对对象:以人类为例,人类通用功能:吃喝拉撒,就可以封装成一个类,不同功能:嫖赌毒,就是对象的不同功能.继承,多态… 上码 class Person(object): def __init__(sel ...
随机推荐
- 苹果的编程语言--Swift
今天(2014-6-3)凌晨WWDC2014揭幕了,带来了新语言Swift,据说非常牛逼...所以就找了几个不错的link跟大家分享. 1.Swift的简单介绍,主要介绍了Swift的简单而经常使用的 ...
- 二分查找(c & c++)
typedef int ElemType; C版本号 [递归版本号] int binSearch2(ElemType List[] ,int x,int head,int tail){ //递归版本号 ...
- css中的绝对定位和相对定位(详解,总结)
css中的绝对定位和相对定位(详解,总结) 总结: 设置绝对定位或者相对定位后都从文档中浮起来了,区别是相对定位还占着原来的位置,绝对定位不占着原来的位置,可以种z-index来改变元素的浮动的堆叠次 ...
- CPPCMS库在Windows下的使用
标题:CPPCMS库在Windows下的使用时间:2012-7作者:Kagula 环境:[1]WinXP SP3[2]VisualStudio2008 SP1[3]ZLib 1.2.7[4]PCRE ...
- Doubles
http://poj.org/problem?id=1552 #include<stdio.h> ; int main() { int n,f[N],g[N]; int cnt; ) { ...
- A simple problem(并查集判环)
http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2497 题意:给定一些点和边的关系,判断S点是否 ...
- go的基础数据类型
一.基础数据类型 在go语言中,数据类型用于申明函数和变量 go语言的类型 数据类型 描述 布尔型 布尔型值的只能是true 和 false ,例如 var b bool = true, 布尔型值声明 ...
- Ubuntu16.04开启root用户,并远程登录
Ubuntu安装完成默认是普通权限的用户,root用户需要手动开启,并且还不含opne-ssh模块 1.给root用户设置密码 # sudo passwd root 会提示输入unix的新密码,这就 ...
- 自学Python四 爬虫基础知识储备
首先,推荐两个关于python爬虫不错的博客:Python爬虫入门教程专栏 和 Python爬虫学习系列教程 .写的都非常不错,我学习到了很多东西!在此,我就我看到的学到的进行总结一下! 爬虫就是 ...
- windows phone媒体应用开发
MediaElement 可以播放许多不同类型的音频和视频媒体. MediaElement 是一个可以在其表面显示视频的矩形区域,也可以播放音频.MediaElement 支持触控输入事件. 使用属性 ...