package main
import (
"factory/model"
"fmt"
)
func main() {
var stu=model.NewStudent("zhangsan",88.5)
fmt.Println(*stu) //{zhangsan 88.5}
}
model/student.go
package model
type student struct {
Name string
Score float64
}
//因为student结构体是私有的,因此是只能在model使用
//工厂模式
func NewStudent(n string,s float64) *student{
return &student{
Name:n,
Score:s,
}
}
封装就是把抽象出的字段和对字段的操作封装在一起,数据被保护在内部,程序的其他包只有通过被授权的操作才能对字段进行操作
1. 字段变成使用
2. 通过工厂模式代替构造函数
3. 建立get/set方法给外部进行调用
继承可以解决代码复用
当多个结构体存在相同的属性(字段)和方法时,可以从这些结构体中抽象出结构体,在该结构体中定义这些相同属性和方法
其他的结构体不需要重新定义这些属性和方法,只需要嵌套一个匿名结构体即可
注意事项:
1. 结构体能使用匿名结构体的所有方法和字段
2. 当结构体和匿名结构体有相同的字段或者方法时,编译器采用就近访问原则访问,如希望访问匿名结构体的字段和方法,可以通过匿名结构体名来区分
3. 结构体嵌入二个(多个)匿名结构体,如二个匿名结构体有相同的字段和方法(同时结构体本身没有同名的字段和方法),在访问时,就必须明确指定匿名结构体名字,否则会报错
4. 如果一个struct嵌套一个有名结构体,这种模式就是组合,如果组合关系,那么在访问组合的结构体的字段或者方法时,必须带上结构体的名字
5. 嵌套匿名结构体后,也可以在创建结构体变量(实例)时,直接指定各个匿名结构体字段的值
type A struct{
字段
}
type B struct{
A
字段
}
多继承:
如果一个struct嵌套了多个匿名结构体,那么该结构体可以直接访问嵌套的匿名结构体的字段和方法,从而实现了多重继承
变量具有多种形态.多态特征是通过接口实现的,可以按照统一的接口来调用不同的实现,这时接口变量就呈现不同的形态
interface类型可以定义一组方法,但是这些不需要实现,并且interface不能包含任何变量.到某个自定义类型要使用的时候,在根据具体情况把这些方法写出来(接口的 所有方法必须全部继承与java接口意义一致)
定义格式 type interface_name interface{方法}
接口注意事项和细节:
1. 接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的变量
2. 接口中所有的方法都没有方法体
3. 在Golang中,一个自定义类型需要将某个接口的所有方法都实现,我们说这个自定义类型实现了该接口
4. 一个自定义类型只有实现了某个接口,才能将该自定义类型的实例赋给接口类型
5. 只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型
6. 一个自定义类型可以实现多个接口
7. Golang接口中不能有任何变量
8. 一个接口可以继承多个别的接口,这时如果要实现A接口,也必须将BC接口都实现
9. interface类型默认是一个指针(引用类型),如果没有对interface初始化就使用,那么会输出nil 10空接口没有任何方法,所以所有类型都可以实现空接口
类型断言,由于接口是一般类型,不知道具体类型,如果要转成具体类型,就需要使用类型断言,类型要相匹配,不然会报错
var t float32
var x interface{}
x=t
y,ok:=x(.float32)//转成float,带检查
if ok==true{
fmt.PrintLn("ok")
}else{
fmt.Println("err")
}
package main
import (
"fmt"
"os"
)
/*
面向对象小案例:家庭收支记账项目
需求分析:
1.收支明细
2.登录收入
3.登记支出
设计阶段:
------------家庭收支记账软件-------------------
1.收支明细
2.登录收入
3.登记支出
4.退出
请选择(1-4):1
------------当前收支明细记录-------------------
收支 账户 收支金额 说明
------------登录收入-------------------
本次收入金额:1000
本次收入说明:有人发红包
------------登录完成-------------------
------------登记支出-------------------
本次支出金额:1000
本次支出说明:有人发红包
*/
//建立家庭收支结构体
type FamilyAccount struct {
//定义选项
choice string
//定义余额
balance float64
//定义每次收支金额
money float64
//每次收支说明
note string
//收入情况说明
details string
}
//收支明细记录
func (this *FamilyAccount) showDetails(){
fmt.Println("------------当前收支明细记录-------------------")
fmt.Printf("收支\t账户\t收支金额\t说明\n")
}
//收入
func (this *FamilyAccount) income(){
fmt.Print("本次收入金额:")
fmt.Scanln(&this.money)
this.balance+=this.money
fmt.Print("本次收入说明:")
fmt.Scanln(&this.note)
this.details+=fmt.Sprintf("收入\t%v\t%v\t %v\n",this.balance,this.money,this.note)
}
//支出
func (this *FamilyAccount) pay(){
fmt.Print("本次支出金额:")
fmt.Scanln(&this.money)
if this.money>this.balance{
fmt.Printf("余额的金额不足,无法付款\n")
return
}
this.balance+=this.money
fmt.Print("本次支出说明:")
fmt.Scanln(&this.note)
this.details+=fmt.Sprintf("支出\t%v\t%v\t %v\n",this.balance,this.money,this.note)
}
func (this *FamilyAccount) MainMenu(){
for{
fmt.Println("------------家庭收支记账软件-------------------")
fmt.Println("------------1.收支明细")
fmt.Println("------------2.登录收入")
fmt.Println("------------3.登记支出")
fmt.Println("------------4.退出")
fmt.Print("请选择(1-4):")
fmt.Scanln(&this.choice)
switch this.choice {
case "1":
fmt.Println("------------当前收支明细记录-------------------")
fmt.Printf(this.details)
break
case "2":
this.income()
break
case "3":
this.pay()
break
case "4":
os.Exit(1)
default:
fmt.Print("请输入正确选项\n")
}
}
}
func main() {
familyAccount:=FamilyAccount{
choice: "",
balance: 1000,
money: 0,
note: "",
details: "收支\t账户\t收支金额\t说明\n",
}
familyAccount.MainMenu()
}