go语言中的“继承”对比Java中的继承

在 Go 语言中没有传统面向对象编程语言中的类继承概念。

然而,Go 语言通过组合和接口来实现类似的代码复用和多态特性

组合是指将一个结构体嵌套在另一个结构体中,以复用其字段和方法。

什么是组合,组合就是嵌入式结构体

接口则定义了一组方法签名,只要某个类型实现了这些方法,就被认为实现了该接口,可以在需要该接口的地方使用

虽然 Go 语言没有直接的继承机制,但通过组合和接口的灵活运用,可以达到类似于继承带来的代码组织和复用效果。

举个简单的例子

package main

import (
    "fmt"
    "github.com/gogf/gf/frame/gdb"
    "github.com/gogf/gf/frame/gmvc"
)

// 假设 gdb.Model 定义了一些方法
type Model struct{}

func (m Model) FindData() {
    fmt.Println("Finding data...")
}

// gmvc.M 结构体组合了 gdb.Model
type M struct {
    gdb.Model
}

func main() {
    m := M{}
    m.FindData() 
}

在上述示例中,M 结构体中包含了 gdb.Model 类型的字段,从而可以使用 gdb.Model 中定义的方法。

请注意,这并不是真正的继承,而是 Go 语言中常见的组合方式。

再举一个例子是

Go 语言中组合和接口的实现

package main

import "fmt"

// 定义一个被组合的结构体
type Component struct {
    Value int
}

// 定义一个方法
func (c Component) PrintValue() {
    fmt.Println("Value:", c.Value)
}

// 定义组合结构体
type Composite struct {
    Component
    Name string
}

func main() {
    composite := Composite{
        Component: Component{Value: 42},
        Name:      "Composite Object",
    }

    // 直接调用被组合结构体的方法
    composite.PrintValue()
}

func main() {
    composite := Composite{
        Component: Component{Value: 42},
        Name:      "Composite Object",
    }

    // 直接调用被组合结构体的方法
    composite.PrintValue()
}

在 main 函数中:

  • 创建了一个 Composite 类型的变量 composite 。
  • 在初始化 Composite 时,同时初始化了其中组合的 Component 结构体,并为其 Value 字段赋值为 42,还为 Name 字段赋值为 "Composite Object" 。

然后,直接通过 composite 调用了从 Component 结构体组合而来的 PrintValue 方法

接口示例:

package main

import "fmt"

// 定义接口
type Shape interface {
    Area() float64
}

// 定义圆形结构体并实现接口
type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return 3.14 * c.Radius * c.Radius
}

// 定义矩形结构体并实现接口
type Rectangle struct {
    Width  float64
    Height float64
}

func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

func printArea(s Shape) {
    fmt.Println("Area:", s.Area())
}

func main() {
    circle := Circle{Radius: 5}
    rectangle := Rectangle{Width: 4, Height: 6}

    printArea(circle)
    printArea(rectangle)
}

在上述组合示例中,Composite 结构体通过包含 Component 结构体来复用其方法和字段。

在接口示例中,定义了 Shape 接口,Circle 和 Rectangle 结构体分别实现了该接口的 Area 方法,通过 printArea 函数以接口类型作为参数实现多态。

那么这种Go 语言通过组合和接口来实现类似的代码复用和多态特性和java继承有什么区别呢?

  1. 关系紧密程度:Java 继承是一种强耦合的关系,子类与父类之间的关系紧密。而 Go 语言的组合是一种更松散的关系,组合的结构体可以独立存在和使用。

  2. 方法重写:在 Java 继承中,子类可以重写父类的方法。在 Go 语言组合中,没有直接的方法重写概念,而是通过重新定义组合结构体中的方法来实现类似效果。

  3. 多态实现:Java 通过继承和方法重写实现多态。Go 语言通过接口和实现接口的不同类型来实现多态。

  4. 代码灵活性:Go 语言的组合和接口使得代码更灵活,更容易组合和替换不同的组件,而 Java 继承在复杂的继承层次结构中可能会导致一些问题,如脆弱的基类问题等。

Java 继承

class Animal {
    public void makeSound() {
        System.out.println("Some default sound");
    }
}

class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Bark");
    }
}

public class JavaInheritanceExample {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.makeSound(); 
    }
}

在 Java 中,通过 extends 关键字实现继承。子类 Dog 继承了父类 Animal 的方法,并且可以重写父类的方法。

Go 语言组合

package main

import "fmt"

// 定义一个被组合的结构体
type SoundMaker {
    MakeSound func()
}

// 定义一个新的结构体,并组合 SoundMaker
type Dog struct {
    SoundMaker
}

func main() {
    dog := Dog{
        SoundMaker: SoundMaker{
            MakeSound: func() {
                fmt.Println("Bark")
            },
        },
    }
    dog.MakeSound()
}

在 Go 语言中,通过将 SoundMaker 结构体嵌入到 Dog 结构体中来实现组合。

Go 语言接口

package main

import "fmt"

// 定义接口
type SoundProducer interface {
    MakeSound()
}

// 定义实现接口的结构体
type Dog struct{}

func (d Dog) MakeSound() {
    fmt.Println("Bark")
}

func main() {
    var soundProducer SoundProducer = Dog{}
    soundProducer.MakeSound()
}

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值