【问题标题】:golang: question about interface implementation inheritance - Stack Overflowgolang:关于接口实现继承的问题 - 代码日志
【发布时间】:2019-08-29 22:43:15
【问题描述】:

这个问题是关于在 golang 中“继承”接口实现的最简洁的方法。我理解 Go 没有继承;这个问题是关于人们如何以其他方式实现它,因此引用了继承。

假设定义了一个标准库接口,例如container/heap:https://golang.org/pkg/container/heap/#Interface

假设有一个名为pq.go.go 文件实现了该接口:

//pq.go
import ("container/heap")
type PriorityQueue []*Vertex

func (pq PriorityQueue) Len() int { return len(pq) }

func (pq PriorityQueue) Less(i, j int) bool {
...
}

func (pq PriorityQueue) Swap(i, j int) {
...
}

func (pq *PriorityQueue) Push(x interface{}) {
...
}

func (pq *PriorityQueue) Pop() interface{} {
...
}

现在假设我只想要一个 Tiny 变体,称为 MaxPQ,在 maxpq.go 中,用于覆盖 pq.go 的单个实现细节,例如,覆盖 Less(..)。如何在不直接复制最后一个文件、更改类型名称和更改单个函数的实现(例如 less)的情况下实现这一点?

意思是,有没有办法对一个与另一个非常相似的接口进行新的实现?

这样做,从字面上复制它,似乎很激烈,需要在多个地方进行更改:

//maxpq.go
import ("container/heap")
type MaxPriorityQueue []*Vertex

func (pq MaxPriorityQueue) Len() int { return len(pq) }

func (pq MaxPriorityQueue) Less(i, j int) bool {
...
}

func (pq MaxPriorityQueue) Swap(i, j int) {
...
}

func (pq *MaxPriorityQueue) Push(x interface{}) {
...
}

func (pq *MaxPriorityQueue) Pop() interface{} {
...
}

【问题讨论】:

  • Go 中没有继承。
  • @Adrian 我理解 Go 没有继承;这个问题是关于人们如何以其他方式实现它。
  • 那你能澄清一下你的问题吗?你反复引用继承,但你说你知道没有这样的事情。
  • @Adrian 已编辑。
  • @Tommy 你考虑过嵌入吗?

标签: go


【解决方案1】:

有多种方法可以做到这一点。

你可以在原有类型的基础上定义一个新类型,并委托所有方法:

type OriginalType struct {...}

func (o OriginalType) F() {...}

type NewType OriginalType

func (n NewType) F() { OriginalType(n).F() }

这样,您需要重新定义原始类型的所有方法,因为 NewType 不会“继承” OriginalType 的方法。

你可以嵌入:

type NewType struct {
   OldType
}

现在您有一个 NewType.F() 函数,但它将在 NewType 的 OldType 部分上运行。如果你想重新声明,你可以:

func (n NewType) F() { 
   n.OldType.F(); 
   // Do more stuff
}

如果您通过接口传递任一实例,这将像继承一样工作。那就是:

type IntF interface {
   F()
}

func f(v IntF) {
  v.F()
}

如果你传递一个 NewType,那么 NewType.F 将被调用。

但是,你必须传递一个接口,你不能传递嵌入的结构来获取封闭对象的行为:

func f(v OriginalType) {
   v.F()
}

func main() {
   n:=NewType()
   // f(n) Won't work
   f(n.OriginalType)

上面,只有n的OriginalType部分被发送给函数f,会调用OriginalType.F。

【讨论】:

    【解决方案2】:

    您可以使用合成来尝试这样的事情。

    type iTemp interface {
        func1()
        func2()
    }
    
    type base struct {
    }
    
    func (base) func1() {
        fmt.Println("base func1")
    }
    func (base) func2() {
        fmt.Println("base func2")
    }
    
    
    type child struct {
        base
    }
    
    func (child) func1() {
        fmt.Println("child func1")
    }
    
    func main(){
        printMessage(base{})
        printMessage(child{})
    }
    
    func printMessage(t iTemp) {
        t.func1()
        t.func2()
    }
    

    输出:

    base func1  
    base func2  
    child func1  
    base func2  
    

    在子结构中,您提供了基类 func1 函数的新实现,但您仍然可以访问基类实现,您仍然可以使用 child{}.base.func1() 调用它

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-12
      • 2021-06-24
      • 1970-01-01
      • 2012-04-10
      • 1970-01-01
      • 2012-04-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多