Go 语言的语法非常简洁,没有常见的面对对象的语法支持,但是也可以通过现有语法来实现面对对象。
1. Object
在 Go 中类可以通过 struct
配合 method
来实现
在这个例子中一个鸭子类有 color
, type
两个属性,有 fly
, quack
两个方法,下面是具体的代码实现
type Duck struct {
string
duckType string
duckColor }
func (duck *Duck) fly() {
.Println("I want to fly higher !")
fmt}
func (duck *Duck) quack() {
.Println("quack quack ! ! !")
fmt}
func main(){
:= Duck{
duck : "black",
duckColor: "mallard",
duckType}
.fly()
duck.quack()
duck}
类中元素的隐藏可以通过元素名称大小写来控制,如果是大写则可以在包外引用如果是小写则只能在包中使用
2. Inheritance
Go 语言并不支持直接继承,但是可以通过 组合(Composition) 的方式来达到相同的目的。比如这个例子,一台电脑可以通过 CPU,RAM,主板来组成,
package computer
import "fmt"
type CPU struct {
string
architecture }
func (cpu *CPU) SetArchitecture(arch string) {
.architecture = arch
cpu}
func (cpu *CPU) GetArchitecture() string {
return cpu.architecture
}
type RAM struct {
int
size }
func (ram *RAM) SetSize(size int) {
.size = size
ram}
func (ram *RAM) GetSize() int {
return ram.size
}
type Motherboard struct {
string
category }
func (m *Motherboard) SetCategory(cat string) {
.category = cat
m}
func (m *Motherboard) GetCategory() string {
return m.category
}
type Computer struct {
cpu CPU
ram RAM
mboard Motherboard}
func (c *Computer) SetSpecification(cpu CPU, ram RAM, mboard Motherboard) {
.cpu.SetArchitecture(cpu.GetArchitecture())
c.ram.SetSize(ram.GetSize())
c.mboard.SetCategory(mboard.GetCategory())
c}
func (c *Computer) ShowSpecification() {
.Println("CPU: ", c.cpu.GetArchitecture(), ", RAM: ", c.ram.GetSize(), "GB, Motherboard: ", c.mboard.GetCategory())
fmt}
3. polymorphism
Go 中多态用两种实现方法,一种是通过 interface
来实现,比如下面这个例子 GetArea
接受一个 Shape
类型的结构,因为这里 Rectangle
和 Circle
都实现了 area
所以他们两者都可以作为参数传给 GetArea
。
package polymorph
import (
"fmt"
"math"
)
type Shape interface {
()
area}
type Rectangle struct {
, Y1, X2, Y2 float64
X1}
type Circle struct {
, Yc, Radius float64
Xc}
func (r *Rectangle) area() {
.Println("Rectangle Area : ", (r.X2-r.X1)*(r.Y2-r.Y1))
fmt}
func (c *Circle) area() {
.Println("Circle Area: ", math.Pi*math.Pow(c.Radius, 2))
fmt}
func GetArea(s Shape) {
.area()
s}
还用一种是通过泛型( generics )来实现,这个是在1.18版本来推出的。比如下面这个例子,他可以同时计算 int64
类型与float64
类型的切片和
package main
func sumIntOrFloats[V int64 | float64](vc []V) V {
var s V
for _, v := range vc{
+= v
s }
return s
}
func main(){
:= []int64{1, 2, 3}
a := sumIntOrFloats(a)
r println(r)
}
两种多态的区别在于通过 interface
实现的多态是动态多态,是在运行的时候才确定的,类似与 C++ 的动态调用 ( dynamic dispatch );而通过泛型实现的多态是静态多态,是在编译的时候就确定了,类似与 C++ 中的 template
。