我想为任何坐标类型事物定义一个接口(interface),该接口(interface)实现一个Distance()方法,该方法可用于计算与同一类型的另一个坐标类型事物的距离(可能是笛卡尔坐标系,也可能是时间坐标系,等等)。

这是一般的想法:

    type Distancer interface {
        Distance(other interface{}) int
    }

但是,这不能为Distance()的参数提供类型安全性,它必须是同一类型。例如,我可能具有一个实现Distance()的ParticularTime结构;传递另一个ParticularTime对象作为参数是有意义的,但是传递ParticularLocation根本没有意义。

我怀疑这至少在某些情况下可能在编译时被发现,例如这显然是错误的:
    x := ParticularLocation{}
    y := ParticularTime{}
    distance := x.Distance(y)

有什么办法表达这种限制?还是我必须在Distance()的每个实现中进行运行时类型检查?

我是否以错误的方式思考这个问题?

最佳答案

这是expression problem的同构。如果我们假设距离等于euclidean distance,这也是相对容易概括的,这对于广泛的应用是一个合理的假设。但是,由于Go不支持dependent types或任何花哨的东西,我们将不得不在我们要支持的维数上做出合理的折衷,以支持类型安全。

让我们在前三个维度中实现这一点。

type OneVectorer interface {
    Vector() [1]float64
}

type TwoVectorer interface {
    Vector() [2]float64
}

type ThreeVectorer interface {
    Vector() [3]float64
}

然后是三种类型安全的方法:
func OneDimensionalDistance(a OneVectorer, b OneVectorer) float64 {
    return euclideanDistance(a.Vector()[:], b.Vector()[:])
}

func TwoDimensionalDistance(a TwoVectorer, b TwoVectorer) float64 {
    return euclideanDistance(a.Vector()[:], b.Vector()[:])
}

func ThreeDimensionalDistance(a ThreeVectorer, b ThreeVectorer) float64 {
    return euclideanDistance(a.Vector()[:], b.Vector()[:])
}

func euclideanDistance(a, b []float64) float64 {
    // invariant: a and b have same length
    c := 0.0
    for i, _ := range a {
        c += math.Pow(b[i]-a[i], 2)
    }
    return math.Sqrt(c)
}

因此,时间点可以是一个OneVectorer,一个笛卡尔点是TwoVectorer,依此类推...

您可以方便地定义其他类型,以使程序更具表现力,并在其方法中映射到此矢量算法。

关于go - 请参阅Golang接口(interface)方法中的实现类型,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38750390/

10-16 11:52
查看更多