go语言学习(五)——面向对象编程

主要讲的是“类”和接口&和其他传统语言不一样的地方挺多的,断断续续看了好几天

下面是我的练习代码

// GoStudy0219 project main.go
/*
go语言学习——面向对象编程(1)
go中类型的值语义和引用语义
结构体(类)的定义和初始化
*/
package main

import (
	"fmt"
)

func main() {
	//几种“类”的初始化
	v1 := &character{"Tom", 100, 10, 100} //这样定义出来的v1实际上时“类”的地址

	v2 := new(character) //	等价于v4:=&character{}
	v2.name = "Judy"
	v2.hp = 50
	v2.magic = 150
	v2.attack = 30

	v3 := &character{name: "Jim", hp: 150} //注意是花括号
	v3.magic = 30
	v3.attack = 20

	fmt.Println(v1)
	fmt.Println(v2)
	fmt.Println(v3)
	fmt.Println("*********************")

	//使用类的函数
	v1.addHp(600)
	fmt.Println(v1)
	fmt.Println(v1.hpIsLessThan(*v2))
	fmt.Println(v2)
	fmt.Println("*********************")

	//其他类型
	var v5 Age = 100
	fmt.Println(v5)

	v5.add(10)
	fmt.Println(v5)

	v5.errorAdd(10)
	fmt.Println(v5)
	fmt.Println("*********************")

	//值语义和引用语义
	//基本数据类型int,float之类的时值语义
	//数组和切片是值语义
	//map,channel和interface是引用语义

}

type Age int

func (this *Age) add(target Age) {
	*this += target
}

func (this Age) errorAdd(target Age) {
	this += target
}

//结构体(与其他语言中的类地位相同)
type character struct {
	name   string
	hp     float32
	attack float32
	magic  float32
}

func (this character) hpIsLessThan(target character) bool { //this character 不会改变this
	target.attack = 66
	return this.hp < target.hp
}

func (this *character) addHp(value float32) { //this *character 会改变this
	this.hp += value
}

 

// GoStudy0223 project main.go
/*
go语言学习——面向对象编程(2)
匿名组合
可访问性
*/

package main

import (
	"fmt"
)

func main() {
	fmt.Println("Hello World!")

	var stu *student = &student{1001, *&person{"Tom", 10, true}}
	fmt.Println(stu)
	stu.greet()           //匿名组合,能直接调用匿名的函数的方法
	fmt.Println(stu.name) //匿名组合能够直接调用匿名函数的属性
	stu.walk()            //多态重载的实现

	var tea *teacher = &teacher{55, "Judy", *&person{"Tom", 10, false}}
	fmt.Println(tea.name)
}

type person struct {
	name  string
	age   int
	isMan bool
}

func (this *person) greet() {
	fmt.Println("hello")
}

func (this *person) walk() {
	fmt.Println("walk slow")
}

type student struct {
	studentId int
	person    //匿名组合
}

func (this *student) walk() { //相当于多态重载,外部调用walk时不再执行匿名函数中的walk函数
	this.person.walk() //根据需求,实现了“基类”的函数,
	fmt.Println("walk quick")
}

type teacher struct {
	teacherId int
	name      string //person 里面的name相当于被隐藏了,外部调用teacher.name的时候,person里面的name并不会起作用
	person
}

/*
匿名组合相当于用类型名称(去掉包名部分)作为成员变量的名字,
因此,一个类型中如果同时有类似于person和xxx.person的时候可能会报错,因此要避免这种情况
*/

/*
首字母大写表示包外可访问,首字母小写,表示包外不能访问。
同一包内,不论首字母是大写还是小写都是能访问的
*/

 

// GoStudy0224 project main.go
/*
go语言学习——面向对象编程(3)
接口
*/
package main

import (
	"fmt"
)

func main() {
	fmt.Println("Hello World!")

	var per = &Person{"Tom", 50}
	fmt.Println(per)

	//接口的赋值
	//用对象赋值
	var v1 IAdd = per //这里传入的实际上是类型的地址
	v1.Add(10)
	fmt.Println(per)
	//用接口赋值
	var v2 IPerson = per
	var v3 IWalk = v2 //函数“全”的接口可以像函数“少”的接口赋值;如果几个接口中函数相同,则这几个接口可以相互转换
	v3.Walk()

	if v4, ok := v2.(IRead); ok { //检测,接口v2能不能转换成IRead接口
		v4.Read()
	}

	if v5, ok := v2.(*Person); ok { //检测,接口v2指向的对象类型是不是Person
		fmt.Println(v5)
	}

	var v6 interface{} = per //interface{}是any类型,空接口
	switch v7 := v6.(type) { //检测接口指向对象的类型
	case int:
		fmt.Println(v7, "int")
	default:
		fmt.Println(v7, "other")
	}

	var v8 IPerson2 = per
	v8.Read()

}

type Person struct {
	name string
	age  int
}

func (this *Person) Add(value int) {
	this.age += value
}

func (this *Person) Walk() {
	fmt.Println("walk")
}

func (this *Person) Speak() {
	fmt.Println("speak")
}

func (this *Person) Read() {
	fmt.Println("read")
}

//定义接口
type IWalk interface {
	Walk() //定义接口函数,省略func关键字
}

type IRead interface {
	Read()
}

type ISpeak interface {
	Speak()
}

type IAdd interface {
	Add(value int)
}

type IPerson interface {
	Walk()
	Read()
	Speak()
}

type IPerson2 interface { //接口的组合,等同于上一个接口的写法
	ISpeak
	IRead
	IWalk
}

/*传统语言的接口是一种契约,使用接口的类必须实现接口的所有方法,不同命名空间下的同名接口也被视为两个不同的接口
eg. C# java等需要考虑定义什么接口,在哪个类里面实现接口
go语言中,并不需要考虑上面的问题
*/

 

posted @ 2017-02-24 22:01  个位数  阅读(213)  评论(0编辑  收藏  举报