面向对象的go语言

62 阅读2分钟

 一、go的结构体

type关键字可以声明一个新的数据类型,例如

type myint int

其中myint相当于int的一个别名,比如

var a myint=10
fmt.Printf("type of a=%T\n",a)

会打印出a的类型为myint类型

下面我来介绍一下结构体的定义,如下代码

func main() {
	var book1 Book
	book1.title = "Golang"
	book1.auth = "yjy"
	fmt.Printf("book1: %v\n", book1)
}

接下来我们试着做一些赋值打印吧~

//定义一个结构体
type Book struct {
	title string
	auth  string
}

那么作为结构体,会不会也有值传递和引用传递的区别呢?那我们来浅试一下~

package main

import "fmt"

//定义一个结构体
type Book struct {
	title string
	auth  string
}

//值传递
func changeBook(book Book) {
	//传递一个book的副本
	book.auth = "zqy"
}

//引用传递
func changeBook2(book *Book) {
	//传递的是指针
	book.auth = "zqy"
}
func main() {
	var book1 Book
	book1.title = "Golang"
	book1.auth = "yjy"
	fmt.Printf("book1: %v\n", book1)
	changeBook(book1)
	fmt.Printf("book1: %v\n", book1)
	changeBook2(&book1)
	fmt.Printf("book1: %v\n", book1)
}

 最后打印结果如下图

​编辑

二、类的表示与封装

 特别的,还要说明一下大小写的区别。要知道在golang中大小写是不一样的。首字母大写表示对外public,其他包可以进行访问;首字母小写,其他包不可以访问,为私有属性。

下面我们来看一下如何定一个类,怎么通过setName让他的名字发生变化,看下面的代码~注意看带 “” 与不带 “” 的区别

package main

import "fmt"

//定义一个类,当前类大写首字母,其他包也可以访问
type Hero struct {
	//属性名大写首字母,表示public其他包也可以用
	Name  string
	Ad    int
	Level int
}
//方法名首字母小写,只能当前使用,其他包不能访问
func (this Hero) show(hero Hero) {
	fmt.Printf("Hero: %v\n", hero)
}
func (this *Hero) show2() {
	fmt.Println("Name=", this.Name)
	fmt.Println("Ad=", this.Ad)
	fmt.Println("Level=", this.Level)
}
func (this Hero) getName() string {
	return this.Name
}

func (this *Hero) getName2() string {
	return this.Name
}
func (this Hero) setName(newName string) {
	//this是调用该方法的对象的一个拷贝
	this.Name = newName
}
func (this *Hero) setName2(newName string) {
	//this是调用该方法的对象的一个拷贝
	this.Name = newName
}

func main() {
	//创建一个对象
	hero := Hero{Name: "yjy", Ad: 100, Level: 1}
	hero.show(hero)
	//注意看Name有没有变化
	hero.setName("lisi") //没有变化
	hero.show2()
	hero.setName2("lisi") //会发生变化
	hero.show2()
}

三、继承

 子类继承父类,只需将父类名字放到子类定义中,更方便!!而定义子类对象的方法我也提供了两种,请看下面的代码

package main

import "fmt"

//定义一个父类,当前类大写首字母,其他包也可以访问
type Hero struct {
	//属性名大写首字母,表示public其他包也可以用
	Name string
	Ad   int
}

//定义一个子类
type Super struct {
	Hero
	level int
}

func (this *Hero) Eat() {
	fmt.Println("Hero.Eat().....")
}
func (this *Hero) Walk() {
	fmt.Println("Hero.Walk().....")
}
func (this *Super) Eat() {
	fmt.Println("Super.Eat().....")
}
func (this *Super) flay() {
	fmt.Println("Super.flay().....")
}
func main() {
	//创建一个对象
	hero := Hero{Name: "yjy", Ad: 100}
	hero.Eat()
	hero.Walk()
	//定义一个子类对象
	//super := Super{Hero{"yjy", 10}, 80}
	//另一种定义方法
	var super Super
	super.Name="yjy"
	super.Ad=10
	super.level=80
	
	super.flay()//调用子类方法
	super.Walk()//调用父类方法
	super.Eat()//调用子类方法
}

四、多态

 基本要素:1.有接口(父类)(interface本质)是个指针

                   2.有子类实现接口中全部方法

                   3.父类类型的变量(指针)指向(引用)子类的具体的数据变量

下面我们来看一下代码 

package main

import "fmt"

//interface本质是个指针
type Animal interface {
	Sleep()
	GetColor() string
	GetType() string
}

//具体的类
type Cat struct {
	Color string
}

//定义一个子类
type Dog struct {
	Color string
}

func (this *Cat) Sleep() {
	fmt.Println("Cat Sleep.....")
}
func (this *Cat) GetColor() string {
	fmt.Println("Cat GetColor.....")
	return this.Color
}
func (this *Cat) GetType() string {
	fmt.Println("Cat type.....")
	return "Cat"
}
func (this *Dog) Sleep() {
	fmt.Println("Dog Sleep.....")
}
func (this *Dog) GetColor() string {
	fmt.Println("Dog GetColor.....")
	return this.Color
}
func (this *Dog) GetType() string {
	fmt.Println("Dog type.....")
	return "Dog"
}
func showtype(animal Animal) {
	animal.Sleep()
	fmt.Println(animal.GetType())
}
func main() {
	var animal Animal //接口的数据类型,父类指针
	animal = &Cat{"red"}
	animal.Sleep() //调用cat的sleep方法,多态现象
	animal = &Dog{"yellow"}
	animal.Sleep()

	cat := Cat{Color: "red"}
	dog := Dog{Color: "yellow"}
	showtype(&cat)
	showtype(&dog)
}

 既然说到interface,那我们再来了解一下interface吧~

  interface是一个通用万能的类型,interface{}表示一个空接口。为什么说是万能的呢,哈哈,其实像那些基本的数据类型int、string、float、struct.......都实现了interface{},也就是说可以用interface{}类型引用任意的数据类型。下面看一下代码的实现吧~用到了断言机制

package main

import "fmt"

//interface{}万能能类型的测试
func myFun(arg interface{}) {
	fmt.Println("myFun is called")
	fmt.Println(arg)
	//interface{}如何区分 此时引用的底层数据类型到底是什么?
	//interface{}提供”类型断言“的机制
	value, ok := arg.(string) //判断是否为string类型
	if !ok {
		fmt.Println("arg is not string")
	} else {
		fmt.Println("arg is a string type,value=", value)
	}
}

//具体的类
type Cat struct {
	Color string
}

func main() {
	cat := Cat{Color: "red"}
	myFun(cat)
	myFun("abc")
	myFun(10)
	myFun(3.14)
}