方法和对象
去方法
就像其他任何Go函数一样定义方法。当Go函数在有限范围内定义或以特定类型附加时,称为方法。方法提供了一种将行为添加到用户定义类型的方法。方法实际上是包含在关键字func和函数名称之间声明的额外参数的函数。
在Go语言中,方法是一种特殊的函数,作用于某种类型的变量(称为接收器),该变量是放置在方法名称之前的额外参数,用于指定方法所附加的主持人类型。接收器类型可以是任何类型,而不仅仅是结构类型:任何类型都可以具有方法,甚至可以是函数类型或int,bool,字符串或数组的别名类型。
方法的一般格式为:
func(recv接收器类型)methodName(参数列表)(返回值列表){…}
接收方在func关键字之后的方法名称前的()中指定。
这是非结构类型的方法示例:
package main import "fmt" type 乘 int func (m 乘) 十次() int { return int(m * 10) } func main() { var num int fmt.Print("Enter any positive integer: ") fmt.Scanln(&num) mul:= 乘(num) fmt.Println("Ten times of a given number is: ",mul.tentimes()) }
运行该程序时,将得到以下输出:
输入任何正整数:5
给定数字的十倍是:50
C:\golang>
关键字func和函数名称之间的参数称为接收器,并将函数绑定到
指定的类型。当函数具有接收者时,该函数称为方法。
Go中有两种类型的接收器:值接收器和指针接收器。在上面的程序中,使用值接收器声明了tentimes方法。十次接收方被声明为int类型的值。当使用值接收器声明方法时,该方法将始终针对用于进行方法调用的值的副本进行操作。
The 多 变量初始化为 乘 类型。因此,可以使用以下方法访问tentimes方法 多.tentimes() 当我们打电话给 十次 方法,价值 多 是呼叫的接收者值, 十次 方法正在对此值的副本上进行操作。
这是一个程序,该程序显示了通过接收器参数(称为类型的方法集)附加到类型的方法的实现。
package main import "fmt" type salary float64 func (s salary) total() total { return total(s) } type total float64 func (t total) hra() hra { t += t * 0.3 // 30% HRA Addition return hra(t) } func (t total) salary() salary { t -=t * 0.10 // 10% Tax Deduction return salary(t) } type hra float64 func (h hra) basic() basic { h += h * 0.3 // 30% HRA Addition return basic(h) } func (h hra) total() total { return total(h) } type basic float64 func (b basic) total() total { return total(b) } func main() { fmt.Println("第一雇员的工资计算:") sal1 := basic(9000.00) fmt.Println(sal1.total()) fmt.Println(sal1.total().hra().total()) fmt.Println(sal1.total().hra().total().salary()) fmt.Println("\n第二雇员的工资计算:") sal2 := basic(5000.00) fmt.Println(sal2.total()) fmt.Println(sal2.total().salary()) }
运行该程序时,将得到以下输出:
第一雇员的工资计算:
9000
11700
10530
第二雇员的工资计算:
5000
4500
C:\golang>
方法重载
方法可能会根据接收器类型而重载,具有相同名称的方法可以存在于2种不同的接收器类型中,例如在同一包中允许这样做:
func(s * inclTax)薪金(e雇员)雇员
func(s * exclTax)薪金(e雇员)雇员
接收器参数可以作为基本类型的值或指针传递。指针接收器参数在Go中被广泛使用。
您也可以使用指针接收器声明方法。
package main import "fmt" type 乘 int type addition int func (m *multiply) twice() { *m = 乘(*m * 2) } func (a *addition) twice() { *a = addition(*a + *a) } func main() { var 多 乘 = 15 多.twice() fmt.Println(mul) var add addition = 15 add.twice() fmt.Println(add) }
运行该程序时,将得到以下输出:
30
30
C:\golang>
让我们再举一个例子,在该例子中,我们调用一个接收指向Struct的指针的方法。我们通过值和指针调用该方法,并且得到相同的结果。
声明带有指针接收器的方法的示例。
package main import "fmt" type 乘 结构 { num int } func (m *multiply) twice(n int) { m.num = n*2 } func (m 乘) display() int{ return m.num } func main() { fmt.Println("按价值致电") var 多1 乘 // 多1 is a value 多1.twice(10) fmt.Println(mul1.display()) fmt.Println("指针呼叫") 多2 := new(multiply) // 多2 is a pointer 多2.twice(10) fmt.Println(mul2.display()) }
运行该程序时,将得到以下输出:
Call by value
20
Call by pointer
20
在main()中,我们自己不必弄清楚是否要在指针上调用方法,Go会为我们做到这一点。 多1 是一个值, 多2 是一个指针,但是方法调用可以正常工作。
Go中的对象
没有一个类类型的概念可以用作Go中对象的基础。 Go中的任何数据类型都可以用作对象。结构 Go中的type可以接收一组定义其行为的方法。没有所谓的特殊类型 类 要么 目的 存在于GO中。 Go中的strct类型接近其他编程语言中通常称为对象的对象。 Go支持通常归因于面向对象编程的大多数概念。
借助软件包和可扩展类型系统等概念,Go的核心支持物理和逻辑模块化。因此我们能够在Go中实现模块化和封装。
新声明的名称类型不会继承其基础类型的所有属性,并且类型系统会对其进行不同的处理。因此,GO不支持 多态性 通过 遗产但是可以创建对象并使用诸如a之类的类型通过合成来表达其多态关系 结构 或 接口.
让我们从下面的简单示例开始,演示如何将struct类型用作可以实现多态组合的对象。
package main import "fmt" type gadgets uint8 const ( Camera gadgets = iota Bluetooth Media Storage VideoCalling Multitasking Messaging ) type mobile 结构 { make string model string } type smartphone 结构 { gadgets gadgets } func (s *smartphone) launch() { fmt.Println ("推出新的智能手机:") } type 安卓 结构 { mobile smartphone waterproof string } func (a *android) samsung() { fmt.Printf("%s %s\n", a.make, a.model) } type 苹果手机 结构 { mobile smartphone sensor int } func (i *iphone) apple() { fmt.Printf("%s %s\n", i.make, i.model) } func main() { t := &android {} t.make ="Samsung" t.model ="Galaxy J7 Prime" t.gadgets = Camera+Bluetooth+Media+Storage+VideoCalling+Multitasking+Messaging t.launch() t.samsung() }
推出新的智能手机:
三星Galaxy J7 Prime
在上面的程序中组成 遗产 原理是用来实现 多态性 使用 类型嵌入 所支持的机制 结构 类型。在这里,每种类型都是独立的,并且被认为与所有其他类型都不同。上面的程序表明,类型 苹果手机 和 安卓 是通过子类型关系移动的。
方法 t.launch() 但是,无论哪种类型, 苹果手机 也不 安卓,是名为launch()的方法的接收者。 launch()方法是针对智能手机类型定义的。由于智能手机类型已嵌入其中 苹果手机 也不 安卓,launch()方法在范围上被提升为这些封闭类型,因此可以访问。