dtwncxs3547 2019-08-27 15:28
浏览 165

golang:关于接口实现继承的问题

This question is about the cleanest way to "inherit" interface implementations in golang. I understand Go does not have inheritance; this question is about how people achieve it otherwise, hence the quotes around inheritance.

Let's say theres a standard library interface defined, for example container/heap: https://golang.org/pkg/container/heap/#Interface

Lets say there's a .go file called pq.go that implements that interface:

//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{} {
...
}

Now let's say I just want a Tiny variant on this, called MaxPQ, in maxpq.go, for where I want to override a single implementation detail of pq.go, e.g., override Less(..). How do I achieve this without literally copying the last file over, changing the type name, and changing the implementation of the single function, e.g., less?

Meaning, is there a way to make a new implementation of an interface that is very similar to another?

Doing this, literally copying it over, seems drastic and changes would need to be made in multiple places:

//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{} {
...
}
  • 写回答

2条回答 默认 最新

  • doumindang2416 2019-08-27 17:54
    关注

    There are multiple ways you can do this.

    You can define a new type based on the original type, and delegate all methods:

    type OriginalType struct {...}
    
    func (o OriginalType) F() {...}
    
    type NewType OriginalType
    
    func (n NewType) F() { OriginalType(n).F() }
    

    With this, you need to redefine all methods of the original type, as the NewType does not "inherit" the methods of the OriginalType.

    You can embed:

    type NewType struct {
       OldType
    }
    

    Now you have a NewType.F() function, but it will operate on the OldType portion of the NewType. If you want to redeclare that, you can:

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

    This will work like inheritance if you pass either instance through an interface. That is:

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

    If you pass a NewType, then NewType.F will be called.

    However, you have to pass an interface, you cannot pass the embedded struct to get the behavior of the enclosing object:

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

    Above, only the OriginalType part of n is sent to the function f, and OriginalType.F will be called.

    评论

报告相同问题?

悬赏问题

  • ¥15 关于#MATLAB#的问题,如何解决?(相关搜索:信噪比,系统容量)
  • ¥500 52810做蓝牙接受端
  • ¥15 基于PLC的三轴机械手程序
  • ¥15 多址通信方式的抗噪声性能和系统容量对比
  • ¥15 winform的chart曲线生成时有凸起
  • ¥15 msix packaging tool打包问题
  • ¥15 finalshell节点的搭建代码和那个端口代码教程
  • ¥15 Centos / PETSc / PETGEM
  • ¥15 centos7.9 IPv6端口telnet和端口监控问题
  • ¥20 完全没有学习过GAN,看了CSDN的一篇文章,里面有代码但是完全不知道如何操作