• Java仔想在Go中写接口,抽象类,我这写法对吗?
  • 发布于 3小时前
  • 6 热度
    11 评论

如题,Java仔想在 Go 中写类似 interface -> abstract class -> sub class 的玩意

实现出来是这个样子,接受各位 Gopher 的批判

package main

import "fmt"

// Require 必须要子类实现的方法
// 对应 abstract method
type Require interface {
Require()
}

// Hook 可能会被子类重写的方法
type Hook interface {
Require
Test1()
Test2()
}

// IBase 类似 Java 的 interface -> abstract class -> sub class 套娃
type IBase interface {
Hook
Common()
}

// Base abstract class
type Base[T Hook] struct {
hook T
}

func NewBase[T Hook](hook T) *Base[T] {
res := &Base[T]{
hook: hook,
}
return res
}

func (b *Base[T]) Common() {
b.hook.Require()
b.hook.Test2()
b.hook.Test1()
}

func (*Base[T]) Test1() {
fmt.Println("Base.Test1")
}

func (*Base[T]) Test2() {
fmt.Println("Base.Test2")
}

// Sub 抽象类的子类
type Sub struct {
*Base[*Sub]
}

func NewSub() *Sub {
res := &Sub{}
// 注意 %v 输出可能会有套娃死循环
res.Base = NewBase[*Sub](res)
return res
}

// Test1 复用 Base 的 Test1
//func (*Sub) Test1() {
// fmt.Println("Sub.Test1")
//}

// Test2 重写 Base 的 Test2
func (*Sub) Test2() {
fmt.Println("Sub.Test2")
}

// Require 必须要子类实现的 Require 不写会编译报错
func (*Sub) Require() {
fmt.Println("Sub.Require")
}

func main() {
  m := make(map[int]IBase)
m[1] = NewSub()
b := m[1]
b.Common()
  /*
  Output: 
  Sub.Require
  Sub.Test2
  Base.Test1
  */
}

用户评论
  • 远山迷雾
  • 我没理解错的话,说白了你就是想实现一个 “模板方法模式” https://refactoringguru.cn/design-patterns/template-method/go/example
    简单版的代码就是:
    ```go
    type Worker interface {
    MustImplementStep() // 必须被实现的方法
    OptionalHook() // 一个有默认行为的、可选的钩子方法
    }
    
    type BaseWorker struct{}
    
    func (b *BaseWorker) OptionalHook() {
    fmt.Println("-> BaseWorker: 执行默认的钩子逻辑。")
    }
    
    type ConcreteWorker struct {
    BaseWorker // 嵌入“基类”,OptionalHook 的默认实现。
    }
    
    // MustImplementStep 实现接口中必须被实现的方法
    func (c *ConcreteWorker) MustImplementStep() {
    fmt.Println("-> ConcreteWorker: 执行必须实现的步骤。")
    }
    
    // 编译期安全检查,如果 ConcreteWorker 未实现 MustImplementStep (注释掉上面方法)会报错
    var _ Worker = (*ConcreteWorker)(nil)
    
    // OptionalHook “重写”嵌入的钩子方法。
    func (c *ConcreteWorker) OptionalHook() {
    fmt.Println("-> ConcreteWorker: 开始执行重写的钩子逻辑。")
    
    // super.method()
    c.BaseWorker.OptionalHook()
    
    fmt.Println("-> ConcreteWorker: 结束执行重写的钩子逻辑。")
    }
    
    func RunTemplate(w Worker) {
    fmt.Println("--- 模板开始 ---")
    w.MustImplementStep()
    w.OptionalHook()
    fmt.Println("--- 模板结束 ---")
    }
    
    func main() {
    worker := &ConcreteWorker{}
    RunTemplate(worker)
    }
    ```

  • 2025/8/27 9:14:00 [ 0 ] [ 0 ] 回复
  • 城南诗客
  • 给一段策略模式代码
    ```
    package main
    import "fmt"
    // 定义 RouteStrategy 为一个接口,包含 CalculateTime 方法
    type RouteStrategy interface {
    CalculateTime(origin, destination string) int
    }
    // 使用函数类型作为策略
    type StrategyFunc func(origin, destination string) int
    // 实现 RouteStrategy 接口的 CalculateTime 方法
    func (sf StrategyFunc) CalculateTime(origin, destination string) int {
    return sf(origin, destination)
    }
    
    // 实现三种策略:步行、骑行、驾车
    
    func WalkStrategyFunc(origin, destination string) int {
    // 假设固定耗时 30 分钟
    return 30
    }
    
    func BikeStrategyFunc(origin, destination string) int {
    // 假设固定耗时 15 分钟
    return 15
    }
    func DriveStrategyFunc(origin, destination string) int {
    // 假设固定耗时 10 分钟
    return 10
    }
    // 路线规划器
    type RoutePlanner struct {
    strategy RouteStrategy
    }
    // 设置策略
    func (rp *RoutePlanner) SetStrategy(strategy RouteStrategy) {
    rp.strategy = strategy
    }
    // 估算出行时间
    func (rp *RoutePlanner) EstimateTime(origin, destination string) int {
    return rp.strategy.CalculateTime(origin, destination)
    }
    
    func main() {
    planner := &RoutePlanner{}
    // 使用步行策略
    walkStrategy := StrategyFunc(WalkStrategyFunc)
    planner.SetStrategy(walkStrategy)
    fmt.Println("Walk Time:", planner.EstimateTime("Home", "School"))
    // 使用骑行策略
    bikeStrategy := StrategyFunc(BikeStrategyFunc)
    planner.SetStrategy(bikeStrategy)
    fmt.Println("Bike Time:", planner.EstimateTime("Home", "School"))
    // 使用驾车策略
    driveStrategy := StrategyFunc(DriveStrategyFunc)
    planner.SetStrategy(driveStrategy)
    fmt.Println("Drive Time:", planner.EstimateTime("Home", "Work"))
    }
    ```

  • 2025/8/27 9:08:00 [ 0 ] [ 0 ] 回复
  • 太伤人
  • 多用 struct 嵌套,少用 interface, 另外 go 不是面向对象的语言,其接口实现都是鸭子类型。其他用法套用函数式编程,强调 go 不是面向对象的语言。
  • 2025/8/27 8:57:00 [ 0 ] [ 0 ] 回复
  • 诗人诗意
  • 我是从 java 过来的,写了几天我发现这么搞太麻烦了,简单方法需要多个实现的场景,都是直接 type xxxxer func(),like:
    -----
    type Pusher func(track Track) error
    
    func PushToLog(track Track) error {
    slog.Infof("track: %+v", track)
    return nil
    }
    
    func NewMqttPusherAdapter(mqttPusher *MqttPusher) Pusher {
    return mqttPusher.Push
    }

  • 2025/8/27 8:53:00 [ 0 ] [ 0 ] 回复
  • 梦清幽
  • 通常我们定义接口的时候都是
    type IFIrst interface{
    FirstFunc()
    }
    
    type ISecond interface{
    SecondFunc()
    }
    
    type Entity struct{
    }
    
    func (e *Entity)FirstFunc(){
    print("first called")
    }
    
    func (e *Entity)SecondFunc(){
    print("second called")
    }
    
    func main(){
    var obj any
    obj = &Entity{}
    
    if first,ok:=obj.(IFirst);ok{
    first.FirstFunc()
    }
    
    if second,ok:=obj.(ISecond);ok{
    second.SecondFunc()
    }
    }

  • 2025/8/27 8:46:00 [ 0 ] [ 0 ] 回复
  • 花落微凉
  • 站在 gopher 的角度,毫无意义。把你这段放到 ai 里,吐槽得比我还狠。懒得贴了,免得毁号,总结一句话就是,你在给 struct 硬塞一个万能爹,其实它只缺一把接口形状的刀子。
  • 2025/8/27 8:41:00 [ 0 ] [ 0 ] 回复