go 封装、继承、接口、多态


封装

  • 隐藏实现细节,需要通过被授权的操作方法操作数据;
  • 可以对数据进行验证保证安全合理;

go 实现封装

  • 结构体、字段的首字母小写(实际开发时没那么严格,因为封装就没那么严格)
  • 提供首字母大写的 get/set 方法操作属性/字段

继承

  • 字段和方法的重用;
  • go 中使用 匿名结构体实现继承机制;
  • 完全访问:结构体可以使用嵌套匿名结构体的所有字段和方法,首字母大写、小写的字段、方法都可以使用。
  • 简化访问:匿名结构体字段的访问可以简化;本结构体有指定的字段时直接使用,没有时去继承的结构体中查找;
  • 就进访问:当结构体和 匿名结构体具有相同的字段或者方法时,编译器采用就进访问原则,如果要访问匿名结构体的字段和方法,可以通过匿名结构体名来区分;
  • 支持多继承:一个结构体中嵌套多个匿名结构体,从而实现多继承。在编程实践中,为了代码可读性简洁性,尽量不要使用多继承;
  • 如果嵌入的匿名结构体有相同的字段、方法名,在访问时,通过匿名结构体类型名来区分;
  • 匿名基本数据类型:结构体的匿名字段可以是基本数据类型;但一个类型只能有一个,否则无法区分;
  • 嵌套匿名结构体后,也可以在创建结构体实例时,直接给各个匿名结构体字段赋值;
  • 可嵌入指针/匿名结构体指针:嵌入时也可以是匿名结构体的指针;
  • 结构体的字段可以是结构体类型的;(组合)

接口

  • 接口中可以定义一组方法,但不需要实现,不需要方法体。并且接口中不能包含任何变量;
  • 实现接口时,要 实现所有的方法 才是实现;go 中不需要显式实现接口,也没有 implement 关键字。
  • go 中实现接口是基于方法的;和实际接口耦合性很低;
  • 例如:A接口(a,b 方法);B接口(a,b 方法); C 结构体实现了a,b 方法,那么C实现了A接口,也可以说实现了B接口;
  • 定义:
type SayHello interface {
SayHello()
}

接口的注意事项

  • 接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的变量;类似父类引用指向子类对象;
  • 只要是自定义数据类型,就可以实现接口,不仅是结构体类型;
  • 一个自定义类型可以实现多个接口;
  • 一个接口可以继承多个别的接口,如果这时要实现这个接口,也必须实现它所继承的接口的方法;
  • interface 类型默认是一个指针(引用类型),如果没有对 interface 初始化就使用,那么会输出 nil
  • object:空接口没有任何方法,所以可以理解为所有类型都实现了空接口,也可以理解为可以把任何一个变量赋值给空接口,类似于java的 object;

多态

  • go 语言中,多态特征是通过接口实现的。可以按照同样的接口来调用不同的实现,这时接口变量就呈现出不同的形态;
  • 特征包括:多态数组,多态参数;
    • 多态数组:
fmt.Println("==>> 数组类型声明为接口,实现多态数组:")
var arr [2]SayHello
arr[0] = Chinese{"中国人"}
arr[1] = American{"美国人"}
fmt.Println("arr=", arr)
  • 多态参数:
func greet(s SayHello) {
	s.SayHello()
}

代码

package main

import (
	"extend_pack/model"
	"fmt"
)

func main() {
	fmt.Println("==>> 封装:")
	person := model.NewPerson("脑斧")
	person.SetAge(18)
	fmt.Println("person= ", *person)
	fmt.Println("person= ", person)
	fmt.Println("person.age=", person.GetAge())

	fmt.Println("\n==>> 继承:")
	cat := &Cat{}
	cat.Animal.Weight = 20
	fmt.Println("简化匿名结构体访问操作:cat.Weight=", cat.Weight)
	cat.Animal.Eat()
	// 简化方法调用操作
	cat.Eat()
	cat.scratch()

	fmt.Println("==>> 继承, 就近访问:")
	cat.Weight = 30
	fmt.Println("cat=", cat)
	fmt.Println("cat.Animal=", cat.Animal)

	fmt.Println("==>> 多继承:")
	c := model.C{A: model.A{Aa: 10, Ab: "aaa"}, B: model.B{Bc: 20, Bd: "bbb"}}
	fmt.Println("c=", c)
	fmt.Println("c.Aa=", c.Aa)
	d := D{ c, 19}
	fmt.Println("d=", d)
	fmt.Println("d.int=", d.int)

	fmt.Println("==>> 匿名结构体指针:")
	pointer := CPointer{Animal: &Animal{73}}
	fmt.Println("pointer=", pointer)
	fmt.Println("*pointer.Animal=", *pointer.Animal)

	fmt.Println("==>> 结构体的字段可以是结构体类型的: 组合:")
	e := E{18, Animal{73}}
	fmt.Println("e=", e)

	fmt.Println("\n==>> 接口:")
	chinese := Chinese{}
	american := American{}
	// 中国人打招呼
	greet(chinese)
	// 美国人打招呼
	greet(american)

	fmt.Println("==>> 接口:使用基础数据类型:")
	var i integer = 10
	i.SayHello()
	fmt.Println("==>> 接口 指向一个实现了它的变量:")
	var s SayHello = i
	s.SayHello()

	fmt.Println("==>> 自定义类型实现多个接口:")
	var m MultiImpl // 不必初始化
	fmt.Println("m=", m)
	var a IA = m
	var b IB = m
	a.a()
	b.b()

	fmt.Println("==>> 空接口,未初始化:")
	var m2 interface{}
	fmt.Println("m2=", m2)
	fmt.Println("==>> 空接口,初始化:")
	// 任何变量都可以赋值给空接口
	var m3 interface{} = m
	fmt.Println("m3=", m3)

	fmt.Println("==>> 数组类型声明为接口,实现多态数组:")
	var arr [2]SayHello
	arr[0] = Chinese{"中国人"}
	arr[1] = American{"美国人"}
	fmt.Println("arr=", arr)
}
// MultiImpl 自定义类型实现多个接口
type MultiImpl struct {

}

func (i MultiImpl) a(){
	fmt.Println("a....")
}

func (i MultiImpl) b(){
	fmt.Println("b....")
}

type IA interface {
	a()
}
type IB interface {
	b()
}

// int 实现接口
type integer int
func (i integer) SayHello(){
	fmt.Println("i'm alias of int....")
}

// SayHello 定义接口
type SayHello interface {
	SayHello()
}

// Chinese 定义一个结构体,用于实现 SayHello 接口
type Chinese struct {
	Name string
}
func (person Chinese) SayHello() {
	fmt.Println("中国人说:你好...")
}

type American struct {
	Name string
}
func (person American) SayHello() {
	fmt.Println("美国人说:hello...")
}

// 定义一个函数,接收实现 SayHello 接口的变量
func greet(s SayHello) {
	s.SayHello()
}


// E 组合
type E struct {
	a int
	b Animal // 组合
}

// CPointer 匿名结构体指针
type CPointer struct{
	*Animal
	string
}

// D 匿名基本数据类型
type D struct {
	model.C
	int
}

type Animal struct {
	Weight float32
}

func (animal *Animal) Eat() {
	fmt.Println("==>> :eat...")
}

type Cat struct {
	Animal
	Weight float32
}

func (cat *Cat) scratch() {
	fmt.Println("==>> :scratch...")
}

func (cat *Cat) String() string {
	return fmt.Sprintf("weight=%v", cat.Weight)
}

func (cat *Cat) Info() string {
	return fmt.Sprintf("weight=%v", cat.Weight)
}

  • extend_pack/model/multiExt.go:
package model

type A struct {
	Aa int
	Ab string
}

type B struct {
	Bc int
	Bd string
}

type C struct {
	A
	B
	int
}
  • extend_pack/model/person.go:
package model

import "fmt"

type person struct {
	Name string
	age int
}

func NewPerson(name string) *person{
	return &person{
		Name: name,
	}
}

func (person *person) SetAge(age int) {
	person.age = age
}


func (person *person) GetAge() int{
	return person.age
}

func (person *person)String() string{
	str := fmt.Sprintf("Name= %v, Age= %v", person.Name, person.age)
	return str
}

运行结果

==>> 封装:
person=  {脑斧 18}
person=  Name= 脑斧, Age= 18
person.age= 18

==>> 继承:
简化匿名结构体访问操作:cat.Weight= 0
==>> :eat...
==>> :eat...
==>> :scratch...
==>> 继承, 就近访问:
cat= weight=30
cat.Animal= {20}
==>> 多继承:
c= {{10 aaa} {20 bbb} 0}
c.Aa= 10
d= {{{10 aaa} {20 bbb} 0} 19}
d.int= 19
==>> 匿名结构体指针:
pointer= {0xc00000c0f0 }
*pointer.Animal= {73}
==>> 结构体的字段可以是结构体类型的: 组合:
e= {18 {73}}

==>> 接口:
中国人说:你好...
美国人说:hello...
==>> 接口:使用基础数据类型:
i'm alias of int....
==>> 接口 指向一个实现了它的变量:
i'm alias of int....
==>> 自定义类型实现多个接口:
m= {}
a....
b....
==>> 空接口,未初始化:
m2= <nil>
==>> 空接口,初始化:
m3= {}
==>> 数组类型声明为接口,实现多态数组:
arr= [{中国人} {美国人}]

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值