带有空接口的“通用”代码中的强制类型

我正在阅读这本书http://algs4.cs.princeton.edu/home/,我认为将Go中的示例作为学习练习来实现会很好,但是该书使用Java作为其语言来描述。


第一章中的一章讨论了设置一些核心数据类型/容器样式类以供以后重用,但是我很难将它们设置为Go设置,这主要是因为这些数据类型似乎喜欢使用Java泛型。


例如,我编写了以下代码


package bag


type T interface{}

type Bag []T


func (a *Bag) Add(t T) {

    *a = append(*a, t)

}


func (a *Bag) IsEmpty() bool {

    return len(*a) == 0

}


func (a *Bag) Size() int {

    return len(*a)

}

从某种意义上说,这可以正常工作,我可以将项目添加到中,Bag并检查其大小和所有内容。但这也意味着以下代码是合法的


a := make(bag.Bag,0,0)

a.Add(1)

a.Add("Hello world!")

a.Add(5.6)

a.Add(time.Now())

我只是想知道是否有任何强制类型的方式,使其符合类似于以下内容的合同


Bag<T> bagOfMyType = new Bag<T>()

例如


Bag<Integer> bagOfInts = new Bag<Integer>()

我知道Go没有泛型,并且它们并不是真正的The Go Way,但我只是想知道是否有可能在编译时“强制”执行任何操作(可能没有)


人到中年有点甜
浏览 185回答 2
2回答

四季花海

我是Go我的新手,所以我很好奇是否有人会得到更好的答案,但是我是这样看的:您希望在编译时强制执行,当在Add()上调用时IntSlice,其参数为int。好吧,这是您的操作方式:func (i *IntSlice) Add(t int) {    *i = append(*i, t)}由于没有泛型,因此Add()每种类型的方法都会有所不同Bag,因此Bag假设您需要,接口将变为:type Bag interface {    IsEmpty() bool    Size() int}这对我来说很有意义,因为您不能Bag绕过一圈,只扔任何东西。Bag仅仅知道某物是一个东西还不足以知道如何调用Add()它。您必须知道Bag您要处理的是哪种类型。您可以使接口特定于该类型,例如IntBag,但是由于实际上只有一种类型可以满足该接口,因此您也可以删除该接口并将其名称更改IntSlice为IntBag。基本上,这意味着完全放弃所有类似于泛型的东西,而只是使用一些可以满足您需要的方法来创建类型:type IntBag []intfunc (b *IntBag) Add(i int) {    *b = append(*b, i)}func (b IntBag) IsEmpty() bool {    return len(b) == 0}func (b IntBag) Size() int {    return len(b)}更新:有时泛型确实会派上用场。在我看来,我们只能根据具体情况选择最适合特定问题的方法。使用空接口和反射,您可以得到一些类似泛型的行为,但是它看起来很丑陋,并且您放弃了一些编译时类型检查。或者您放弃泛型而进行一些代码重复。或者您只是用完全不同的方式来做。几周前,我问了一个问题,关于我应该如何使用Go来处理看起来像我需要类层次结构的问题。答案基本上是没有通用的解决方案。视情况而定。我认为泛型也是如此:Go中没有泛型,也没有将基于泛型的解决方案转换为Go的通用解决方案。在许多情况下,您可能会在另一种语言中使用泛型,但是在Go中,接口是完全足够的(或真正的亮点)。您的示例在这里,接口并不是真正合适的替代品。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go