如何编写具有不同签名的同一方法的多个实现

How to write several implementation of the same method that have a different signature

我有几个相同方法的实现SetRateForMeasure:

package repartition

type Repartition interface {
    Name() string
    Compute(meters []models.Meter, totalsProd, totalsConso map[string]float64) []models.Meter
    SetRateForMeasure(meter models.Meter, measure models.Measure, total float64) float64
}

然后,在我的代码中(在repartition.go中),我称之为:

rate := repartition.SetRateForMeasure(meter, measure, total)

其中repartition是之前定义的接口。

问题是,当我添加此方法的新实现时,我的函数的参数可能会有所不同。

例如,静态重新分区使用仅在这种情况下使用的静态百分比。

我最后添加了参数,这样我就有了所有方法的通用接口,但结果是有很多未使用的参数,具体取决于实现。

如果我将它添加到公共接口,它将不会被其他定义使用。

我试图从我的接口定义中删除这个方法,但是现在

rate := repartition.SetRateForMeasure()

不再定义。

我应该如何组织我的代码?

Go 中没有函数重载,所以你不能用不同的参数声明同一个函数。不过,您可以通过几种方式实现这一点:

  • 您可以添加多个具有不同名称和签名的函数
  • 您可以更改函数以接受结构而不是参数
SetRateForMeasure(args SetRateOptions) float64

type SetRateOptions struct {
 Meter models.Meter
 Measure models.Measure
 Total float64
 Percentage *float64 // If nil, use default percentage
 ... // more parameters as needed
}

Go 不支持方法覆盖。您可以使用不同的名称定义方法,这些方法采用不同的参数 或者你可以声明方法接受参数结构。

type SetRateParams struct {
    Meter    models.Meter
    Measure  models.Measure
    Total    float64
}

type Repartition interface {
    SetRateForMeasure(params SetRateParams) float64
}

您可以选择将结构中的参数声明为指针,这样您就可以用 nil 表示“未提供”语义,而不是使用零值。这可能与 0 可能是有效值的数字参数有关。

使用 struct 参数还有一个优点,即如果您决定在 6 个月后添加一个额外的参数(您只需将其添加到结构中),则不必更改所有调用站点。

interface{} varargs 也有更糟糕的解决方案,为了说明什么是可能的,但除非你讨厌类型安全,否则我不建议这样做。