go笔记07

面向对象编程:

抽象的介绍:

我们在前面定义一个结构体时候,实际上就是把一类事物共有的属性(字段)和行为提取出来,形成一个物理模型(结构体),这种研究问题的方法就是抽象。

下面是一个银行模型

银行账号->属性(字段):

  1. 账号 2.密码 3.余额

(行为)方法:

1.存款 2.取款 3.查询

账号结构体:Account

代码实现:

package main
import "fmt"
type Account struct{
	AccountNam string
	Pwd string
	TheLest int
}
func (ac *Account) SaveMoney(n int){
	ac.TheLest += n
	fmt.Println("存款成功...")
	fmt.Printf("该账号名: %s\n您的余额为: %d",ac.AccountNam,ac.TheLest)
}
func (ac *Account) UseMoney(n int){
	ac.TheLest -= n
	fmt.Println("取款成功...")
	fmt.Printf("该账号名: %s\n您的余额为: %d",ac.AccountNam,ac.TheLest)
}
func (ac *Account) LookTl(){
	fmt.Printf("该账号名: %s\n您的余额为: %d",ac.AccountNam,ac.TheLest)
}
func main(){
	var ac = Account{
		AccountNam: "mary",
		Pwd : "123123",
		TheLest: 52369,
	}
	fmt.Printf("功能:\n1. 存款\n2.取款\n3.查询本账号信息\n")
	var cmd int
	fmt.Println("您需要...")
	fmt.Scanf("%d",&cmd)
	switch cmd{
	case 1:
		var money int
		fmt.Println("请输入储存金额 :")
		fmt.Scanf("%d",&cmd)
		ac.SaveMoney(money)
	case 2:
		var money int
		fmt.Println("请输入取款金额 :")
		fmt.Scanf("%d",&cmd)
		ac.UseMoney(money)
	case 3:
		ac.LookTl()
	default :
		fmt.Println("输入有错误....",cmd)
	}
}

另外可以对方法进行系统优化,对操作者进行输入密码处理。

演示代码如下:

package main
import "fmt"

type Account struct{
	AccountNo string
	Pwd string
	Balance float64
}

//方法:
//1. 存款:
func (account Account) Deposite(money float64,pwd string){
	if pwd != account.Pwd{//有密码不等与account.Pwd,就输出密码错误
		fmt.Println("您输入的密码有错误...")
		return
	}//代表次方法的结束
	if money<=0 {
		fmt.Println("您输入的金额错误...")
		return
	}
	account.Balance += money
	fmt.Println("存款成功....")
	fmt.Printf("余额 : %f\n",account.Balance)
}

func (account Account) WithDraw(money float64,pwd string){
	//看下密码是否正确
	if pwd != account.Pwd{//有密码不等与account.Pwd,就输出密码错误
		fmt.Println("您输入的密码有错误...")
		return
	}//代表次方法的结束
	if money<=0 {
		fmt.Println("您输入的金额错误...")
		return
	}
	account.Balance -= money
	fmt.Println("取款成功....")
	fmt.Printf("余额 : %f\n",account.Balance)
}

func (account Account) Query(pwd string){
	//看下密码是否正确
	if pwd != account.Pwd{//有密码不等与account.Pwd,就输出密码错误
		fmt.Println("您输入的密码有错误...")
		return
	}//代表次方法的结束
	fmt.Println("您的信息为:")
	fmt.Printf("AccountNumber : %s\nPwd : %s\nBalance :%f",
		account.AccountNo,account.Pwd,account.Balance)
}

func main(){
	//测试:
	account := Account{
		AccountNo: "小明",
		Pwd : "6",
		Balance: 856.99,
	}
	account.Query("6")
	fmt.Println()
	account.Deposite(200.0,"6")
	fmt.Println()
	account.Query("6")
	fmt.Println()
	account.WithDraw(150.0,"6")
	fmt.Println()
	account.Query("6")
}

其中还可以加上去一个操作菜单,再用switch语句进行命令和选项。

面向对象编程的三大特性-封装

封装基本介绍

封装就是把抽象出的字段和对字段的操作封装在一起,数据被保护在内部,程序的其他包只有通过被授权的操作,才能对字段进行操作。

封装的理解和好处

  1. 隐藏细节
  2. 可以对数据进行验证,包证安全的可靠性

如何体现封装

  1. 对结构体中的属性(字段)进行封装(结构体内的字段小写字母,就是简单的封装)
  2. 通过方法、包实现封装

封装的实现步骤

  1. 将结构体、字段首字母小写(不可以导出,其他的包不能使用、类似其他的语言中的private)
  2. 给结构体所在包提供一个工厂模式的函数,首字母大写。(类似其他语言的public)
  3. 提供一个首字母大写的Set方法,用于对属性判断属性判断并复制
func (var 结构体类型名) SetXxx(参数列表){
    return var.age
}

特别说明:在golang中开发中并没有特别强调封装,golagn本身对面向对象的特性进行了做了简化的

快速入门案例

看一个程序(persion.go),不能随便查看人的年龄、工资等隐私,并对输入的年龄进行合理的验证。设计model包(persion.go)main包(main.go 调用Persion结构体)

代码实现:

model/persion.go

persion.go:
package model
import "fmt"

type persion struct{
	Name string
	age int
	salary float64//小写字母不能直接访问
}

//协议个工厂模式,相当与别的语言的构造函数
func NewPersion(name string) *persion{
	//返回的是一个persion结构体的指针
	return &persion{
		Name : name ,
	}
}//相当于SetName函数
func (p *persion) SetAge(age int){
	if age >0&& age < 150{
		p.age = age
	}else {
		fmt.Println("您输入的年龄有错误...")
		//给以个默认值
	}
}//这样就对输入年龄有进行合理的验证了
//另外还要设置一个Get函数,设置一对
func GetAge(p *persion) int{
	return p.age
}

func (p *persion) SetSalary(money float64){
	if money >=3000&&money<=30000{
		p.salary =money
	}else {
		fmt.Println("您输入的金额有误....")
	}
}
func GetSalary(p *persion) float64{
	return p.salary
}
main.go:
package main

import(
	"fmt"
	"go_code/oop.ex/oop.ex5/model"
)
func main(){
	p := model.NewPersion("jack")
	fmt.Println(p)
	p.SetAge(88888)
	fmt.Println(p)
	p.SetAge(78)
	fmt.Println(p)
	p.SetSalary(7892.6)
	fmt.Println(p)
}
运行结果:
&{jack 0 0}
您输入的年龄有错误...
&{jack 0 0}
&{jack 78 0}
&{jack 78 7892.6}

练习

要求:1)创建程序,model包中定义一个Account结构体:在main函数中体系那golang的封装性

2)Account皆否提要求具有字段:账号:(长度在6~10之内)、余额(必须大于20)、密码(一定要是六位数)

3)通过SetXxx的方法来给Account的字段赋值。

4)在main函数中测试

model.go:
package model

import "fmt"

type Account struct {
	account string
	balance float64
	pwd string
}

func (p *Account) Setaccount(name string){
	if len(name)>=6&&len(name)<=10{
		p.account = name
	}else {
		fmt.Println("输入账号名格式有错误...")
	}
}

func (p *Account) Setbalance(money float64){
	if money >= 20.0{
		p.balance = money
		fmt.Println("存款成功..,")
	}else {
		fmt.Println("存款金额有错误...")
	}
}
func (p *Account) Setpwd(pwd string){
	if len(pwd)!=6{
		fmt.Println("密码格式有误,只能输入六位数...")
	}else {
		p.pwd = pwd
	}
}
main.go:

package main
import (
	"fmt"
	"go_code/fengzhuang/model"
)
func main(){
	persion := &model.Account{}
	persion.Setaccount("刘杰")
	persion.Setbalance(523.3)
	persion.Setpwd("jinglu")
	fmt.Println(*persion)
}

面向对象三大特性-继承

引出继承的必要性:

1)对于两个或者多个结构体的字段或者是方法几乎相同,但是我们却写了相同的代码,代码复用性不强

2)出现代码重复,而且代码不利于维护,同时也不利于功能的扩展。

3)解决方法-通过继承的凡是来解决

继承的基本介绍:

继承可以解决代码复用,让我们的编程更加接近人类思维

当多个结构体存在相同的属性(字段)和方法时,可以从这些结构体中抽象出结构体,在该结构体这中定义这些相同的方法。

其他的结构体不需要重新定义这些字段和方法,只需要嵌套一个匿名结构体就可以了

嵌套结构体基本语法:

type Goods struct{
    Name string
    Price int
}
type Book struct{
    Goods//在Book结构体中镶嵌了结构体Goods
    Writrer string
}

快速入门:

编写一个学生考试系统,输出小学生,中学生,大学生还有研究生的考试状态

代码;

package main
import "fmt"
type Student struct{
	Name string
	Age int
	Scores float64
}
type Pupil struct{
	Student
}
type Bigpupil struct{
	Student
}
func (stu *Student) State(){
	fmt.Printf("姓名: %s\n年龄: %d\n成绩: %.1f\n",stu.Name,stu.Age,stu.Scores)
}
func (pupil *Pupil) testing(){
	fmt.Printf("%s 在考试当中(小学生)....\n",pupil.Name)
}
func (bigstu *Bigpupil) testing(){
	fmt.Printf("%s 在考试当中(大学生)....\n",bigstu.Name)
}
func main(){
	pupil := &Pupil{Student{
		Name: "jack",
		Age: 15,
		Scores: 98.9,
	}}
	Stu := &Bigpupil{Student{
		Name: "mary",
		Age: 28,
		Scores: 483,
	}}
	pupil.testing()
	pupil.State()
	Stu.testing()
	Stu.State()
}
终端输出:
jack 在考试当中(小学生)....
姓名: jack
年龄: 15
成绩: 98.9
mary 在考试当中(大学生)....
姓名: mary
年龄: 28
成绩: 483.0

继承带来的便利:

1)代码的复用性提高了

2)代码的扩展性和维护性提高了

继承的深入讨论:

1)结构体可以是用嵌套匿名结构体所有的字段和方法,即:首字母大小写的字段、方法都可以使用

2)匿名结构体字段可以简化

package main

import _"fmt"

type A struct{
	name string
	age int
	scores float64
}
type B struct {
	A
	name string
}
//简化定义:
func main(){
	var b B 
	b.name = "jack"//b中字段含有一个字段name
	b.age = 18//简化定义,在b结构体中只有B中含有age
	//相当于 b.A.age = 18
}


对上面代码的流程:

编译器会先看b对应的结构体中是否有name,如果有的话就直接定义的是对应的结构体内的字段中的name,假如没有的话就会在b对应的字段中的结构体中查找name,

如上面的b.age—b对应的结构体中没有age这一个字段,那么,编译器就会去b对应的结构体中的A结构体中查找age这一个字段,就这样一直找下去,找到最近的,假如没有就会报错。

接口:

基本介绍:

Golang中的多态是主要通过接口来实现的

快速入门

package main

import (
	"fmt"
)

//声明(定义)一个接口
type Usb interface{
	//声明两个没有实现的方法
	Start()
	Stop()
}

type Phone struct{

}
//手机实现了Usb的方法
func (phone Phone) Start(){
	fmt.Println("手机开始工作····")
}
func (phone Phone) Stop(){
	fmt.Println("手机停止工作····")
}
//Camera实现了接口Usb
type Camera struct{

}
func (camera Camera) Start(){
	fmt.Println("相机开始工作····")
}
func (camera Camera) Stop(){
	fmt.Println("相机停止工作····")
}


type Computer struct{

}
//编写一个Working方法,接收一个Usb接口类型变量
//只要实现了Usb接口(实现了接口的所有方法)


func (c Computer) Working(usb Usb){
	usb.Start()
	usb.Stop()
}
func main(){
	//测试
	computer := Computer{}
	phone := Phone{}
	camera := Camera{}


	computer.Working(phone)
	computer.Working(camera)
	computer.Working(phone)
}

小结说明:

  • 接口里的所有方法都没有方法体,即接口的方法都是没有实现的方法,接口体现了程序设计的多态和高内聚低耦合的思想
  • Golang中的接口,不需要显示的实现,只要一个变量,含有接口类型中的所有方法,那么这个变量就实现了这个接口,因此,Golang中没有implement这样的关键字

注意事项:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值