Types 无开销的交换机接口实现

Types 无开销的交换机接口实现,types,interface,go,implementation,Types,Interface,Go,Implementation,给定一个接口和两个(或更多)实现,我很难在扩展功能时轻松切换实现 例如,假设有一个接口INumber,它支持Inc和String,并有两个实现numbertin32和numbertin64及其明显的实现。假设我想在INumber之上实现一个EvenCounter。EvenCounter只有两次Inc,应该调用Inc两次。在EvenCounter中,我很难在不使用额外结构的情况下获得正确的类型 type INumber interface { Inc() String() str

给定一个接口和两个(或更多)实现,我很难在扩展功能时轻松切换实现

例如,假设有一个接口INumber,它支持Inc和String,并有两个实现numbertin32和numbertin64及其明显的实现。假设我想在INumber之上实现一个EvenCounter。EvenCounter只有两次Inc,应该调用Inc两次。在EvenCounter中,我很难在不使用额外结构的情况下获得正确的类型

type INumber interface {
    Inc() 
    String() string
}

type NumberInt32 struct {
    number int32
}

func NewNumberInt32() INumber {
    ret := new(NumberInt32)
    ret.number = 0
    return ret
}

func (this *NumberInt32) Inc() { 
    this.number += 1
}

func (this *NumberInt32) String() string {
    return fmt.Sprintf("%d", this.number)
}

// type NumberInt64.... // obvious
这就是我奋斗的地方

type EvenCounter1 INumber // nope, additional methods not possible 
type EvenCounter2 NumberInt32 // nope
func (this *EvenCounter2) IncTwice() {  
for i:=0; i < 2; i+=1 {
    // this.Inc() // Inc not found
    // INumber(*this).Inc() // cannot convert       
    // in, ok := *this.(INumber) // cannot convert
    // v, ok := this.(INumber) // cannot convert
    // a concrete conversion a) does not work and b) won't help
    // here it should be generic
    // v, ok := this.(NumberInt32) 
    // How do I call Inc here on this?
    }
}
我可以接受为每个方法手动实现委托的需要,但是 显然,我希望依赖INumber,而不是具体的实现(即 这意味着要改变很多地方来尝试另一个实现,但是,我希望避免额外的间接寻址和(很可能?)额外的空间 如何避免使用结构并直接说EvenCounter是一个(特定的)INumber以及其他方法

顺便说一句,真正的例子是一组整数和一组整数到整数的映射,数百万个实例都相互交织在一起(不,仅仅映射[int]bool是不够的-太慢了,位集很有趣,取决于用例等等),并通过更改代码中的2-3行来轻松测试集合和映射的不同实现(理想情况下,只是类型,也许 实例的一般创建(resp.make copies)


感谢您的帮助,我希望还没有人问过您……

我不确定我是否正确理解了您想要实现的目标。也许是这样的

package main

import "fmt"

type Num interface {
        Inc()
        String() string
}

type Int32 struct {
        int32
}

func (n *Int32) Inc() {
        (*n).int32++
}

func (n Int32) String() string {
        return fmt.Sprintf("%d", n.int32)
}

type EventCounter interface {
        Num
        IncTwice()
}

type Event struct {
        Num
}

func (e Event) IncTwice() {
        e.Inc()
        e.Inc()
}

func main() {
        e := Event{&Int32{42}}
        e.IncTwice()
        fmt.Println(e)
}
(阿尔斯)


输出

44

使用嵌入的变体实际上并没有嵌入

这将您的示例简化为:

type EvenCounter3 struct {
    INumber
}

func (this *EvenCounter3) IncTwice() {
    this.Inc() // using this.n.Inc() twice makes it slower
    this.Inc()
}
请注意,String()是自动委派的(在Go speak中为“提升”)


至于电话公司()两次使其变慢,这是使用接口的一个限制。接口的要点是不公开实现,因此您无法访问其内部数字变量。

谢谢:大致上,在
事件的定义中,没有围绕
num
的附加结构。但是正如另一个答案所指出的,如果没有给出名称,似乎会有一个自动委托。谢谢:好的,我读的是关于接口的,而不是关于结构的。一个自动委托就可以了。不过我会继承INumber的所有公共方法?通过一个具体的类型,我可以隐藏它们?我不想访问number变量。这个.n.Inc()与这个.Inc()的问题额外的间接方法是this.n-不是对实际方法的调用。匿名嵌入字段的语法感觉正确。但是,一个快速而肮脏的测试(在循环中引发)显示了下面可能存在与命名字段相同的间接寻址。我想我必须接受这一点。谢谢!如果你考虑接口的语义(具体来说):在讨论的场景中,“双重”间接寻址是不可避免的(嵌入“东西”时通过嵌入继承的方法)是一个接口)。
type EvenCounter3 struct {
    INumber
}

func (this *EvenCounter3) IncTwice() {
    this.Inc() // using this.n.Inc() twice makes it slower
    this.Inc()
}