GO语言扩展已有类型|青训营
当我们使用别人的包的时候,如果我们想要拓展一个已有类型,在其他面向对象的语言中,只需要继承一下即可,但是在继承的过程中会遇到很多的不灵活。在GO语言中取消了继承,他有两种方法来扩充别人的类型(或系统类型):
定义别名
在Go语言中,可以使用别名来扩展或拓展已有类型。通过使用别名,您可以为现有的类型创建新的名称,并在新的名称上定义新的方法。这样做的好处是,您可以在不修改原始类型的情况下,为其添加新的功能或行为。
下面是使用别名拓展已有类型的步骤:
-
定义别名:使用
type关键字创建一个新的类型,并给它起一个新的名字。这个新的名字就是别名。 -
定义新方法:在新的别名类型上定义新的方法,这些方法将成为该别名类型的特有行为。
拓展内置类型int
下面是一个示例,展示如何拓展Go语言的内置类型int:
package main
import "fmt"
// 定义一个新的类型别名,取名为MyInt
type MyInt int
// 在MyInt类型上定义一个新的方法Double,用于将值翻倍
func (m MyInt) Double() MyInt {
return m * 2
}
func main() {
// 使用别名类型创建变量
num := MyInt(5)
// 调用MyInt类型上的方法
doubledNum := num.Double()
// 输出结果
fmt.Println("原始值:", num)
fmt.Println("翻倍后的值:", doubledNum)
}
在上面的例子中,我们定义了一个新的类型别名MyInt,它是基于内置类型int创建的。然后,我们在MyInt类型上定义了一个新的方法Double,用于将值翻倍。在main函数中,我们创建一个MyInt类型的变量num,并调用它的Double方法,将其值翻倍,并输出结果。
注意:尽管我们使用了别名拓展int类型,但是别名类型MyInt和原始类型int是不同的类型。虽然它们在底层具有相同的表示和相互转换的能力,但是它们在Go语言中是不可互换的类型。
拓展已有结构体
当使用结构体时,也可以使用别名来拓展已有结构体的功能。以下是一个使用别名拓展结构体的例子:
package main
import "fmt"
// 定义一个Person结构体
type Person struct {
Name string
Age int
Country string
}
// 在Person结构体上定义一个新的方法PrintDetails,用于打印个人信息
func (p Person) PrintDetails() {
fmt.Printf("Name: %s\nAge: %d\nCountry: %s\n", p.Name, p.Age, p.Country)
}
// 定义一个新的类型别名,取名为Employee
type Employee Person
// 在Employee类型上定义一个新的方法SetEmployeeID,用于设置员工ID
func (e Employee) SetEmployeeID(id int) {
fmt.Printf("Setting Employee ID %d for %s\n", id, e.Name)
}
func main() {
// 创建一个Person结构体对象
person := Person{
Name: "Alice",
Age: 30,
Country: "USA",
}
// 调用Person结构体上的方法
person.PrintDetails()
// 使用Employee类型创建一个新的对象
employee := Employee{
Name: "Bob",
Age: 25,
Country: "Canada",
}
// 调用Employee类型上的方法
employee.PrintDetails()
employee.SetEmployeeID(1001)
}
在上面的例子中,我们首先定义了一个Person结构体,其中包含Name、Age和Country三个字段,并定义了一个方法PrintDetails()用于打印个人信息。接下来,我们通过将Person类型赋值给一个新的类型别名Employee来创建一个新的类型。这样一来,Employee类型就具有了Person结构体的所有字段和方法。
在main函数中,我们创建了一个Person类型的对象person和一个Employee类型的对象employee。然后,我们调用了它们各自的方法,包括PrintDetails()方法和SetEmployeeID()方法,展示了如何使用别名类型拓展已有结构体的功能。
使用组合
当使用组合来拓展已有类型时,我们不会使用别名,而是在新的结构体中嵌入一个已有类型,并通过这种嵌入的方式来继承已有类型的字段和方法。这种方式通常称为组合或嵌套结构体。
下面是使用组合扩展已有类型的步骤:
-
定义新的结构体:使用
type关键字定义一个新的结构体,并在其中嵌入一个已有类型。这个已有类型可以是一个自定义结构体、内置类型或其他的扩展结构体。 -
使用已有类型:在新的结构体中可以直接使用已有类型的字段和方法,就像它们是新结构体的一部分一样。
下面是一个示例,展示如何使用组合扩展已有结构体的功能:
package main
import "fmt"
// 定义一个Person结构体
type Person struct {
Name string
Age int
Country string
}
// 在Person结构体上定义一个方法PrintDetails,用于打印个人信息
func (p Person) PrintDetails() {
fmt.Printf("Name: %s\nAge: %d\nCountry: %s\n", p.Name, p.Age, p.Country)
}
// 定义一个新的结构体Employee,嵌入了Person结构体
type Employee struct {
Person
EmployeeID int
}
// 在Employee结构体上定义一个新的方法SetEmployeeID,用于设置员工ID
func (e Employee) SetEmployeeID(id int) {
fmt.Printf("Setting Employee ID %d for %s\n", id, e.Name)
}
func main() {
// 创建一个Employee结构体对象
employee := Employee{
Person: Person{
Name: "Alice",
Age: 30,
Country: "USA",
},
EmployeeID: 1001,
}
// 调用Employee结构体上的方法
employee.PrintDetails()
employee.SetEmployeeID(1002)
}
在上面的例子中,我们定义了一个Person结构体,并在其上面定义了一个PrintDetails()方法。然后,我们定义了一个新的结构体Employee,并在其中嵌入了Person结构体,同时添加了一个新的字段EmployeeID。
在main函数中,我们创建了一个Employee结构体的对象employee,并直接使用Person结构体的字段和方法,包括PrintDetails()方法和Name字段。同时,我们也调用了Employee结构体自己的方法SetEmployeeID()。这样,我们通过组合的方式扩展了Person结构体的功能,让Employee结构体具有了Person结构体的所有功能,并且在此基础上添加了新的字段和方法。
总结
当使用Go语言来拓展已有类型时,有两种常见的方式:
-
使用别名拓展已有类型:
- 使用
type关键字创建一个新的类型别名,将其赋值为已有类型。 - 在新的类型别名上定义新的方法,用于添加新的功能或行为。
- 这种方式创建的别名类型和原始类型是不可互换的,尽管它们在底层具有相同的表示和相互转换的能力。
- 使用
-
使用组合扩展已有类型:
- 使用
type关键字定义一个新的结构体,并在其中嵌入一个已有类型。 - 在新的结构体中可以直接使用已有类型的字段和方法,就像它们是新结构体的一部分一样。
- 这种方式创建的新结构体可以直接使用已有类型的功能,并在此基础上添加新的字段和方法。
- 使用
在示例代码中,我们展示了这两种方式的用法:
-
使用别名拓展已有类型的示例代码展示了如何在
int类型上定义一个新的类型别名MyInt,并在其上面定义新的方法Double()用于翻倍操作。 -
使用组合扩展已有类型的示例代码展示了如何在
Person结构体上定义一个新的结构体Employee,并在其中嵌入Person结构体,同时添加新的字段EmployeeID和方法SetEmployeeID()。
无论使用别名还是组合,都能让我们在不修改原有类型的情况下,为其添加新的功能或行为。选择哪种方式取决于您的需求和设计考虑。使用别名适用于需要对现有类型进行一些扩展,而使用组合适用于创建一种新的、拥有已有类型功能的复合类型。