英文:
Go - Idiomatic way around interface slice issue
问题
我有一个包含有关某人工作时间的 WorkDay 结构体,一个用于保存一组 WorkDay 的 WorkWeek 结构体,以及一个用于保存一组 WorkWeek 的 WorkMonth 结构体。每个结构体都返回在该时间段内工作的总小时数。
这段代码运行得很好,但是在 WorkWeek.HoursWorked()
和 WorkMonth.HoursWorked()
中的重复代码真的让我很烦。我尝试了以下方法,以为自己非常聪明:
func (w WorkWeek) HoursWorked() time.Duration {
return sumHoursWorked(w.WorkDays)
}
func (m WorkMonth) HoursWorked() time.Duration {
return sumHoursWorked(m.WorkWeeks)
}
type countable interface {
HoursWorked() time.Duration
}
func sumHoursWorked(timeFrames []countable) time.Duration {
var totalHours time.Duration
for _, frame := range timeFrames {
totalHours += frame.HoursWorked()
}
return totalHours
}
然而,正如这里所解释的那样,尽管 WorkDay
实现了 countable
接口,但 WorkDay
的切片并不被视为 countable
的切片。
所以,有没有一种巧妙、惯用的方法可以解决这个问题,还是我只能接受重复代码呢?
英文:
I have a WorkDay struct holding data about the times someone worked, a WorkWeek struct to hold a bunch of WorkDays, and a WorkMonth struct to hold a bunch of WorkWeeks. The idea is to have each return the total hours worked during that period.
type WorkDay struct {
StartTime time.Time
EndTime time.Time
}
type WorkWeek struct {
WorkDays []WorkDay
}
type WorkMonth struct {
WorkWeeks []WorkWeek
}
func (w WorkDay) HoursWorked() time.Duration {
// Find hours worked through simple subtraction.
}
func (w WorkWeek) HoursWorked() time.Duration {
var totalHours time.Duration
for _, day := range w.WorkDays {
totalHours += day.HoursWorked()
}
return totalHours
}
func (w WorkMonth) HoursWorked() time.Duration {
var totalHours time.Duration
for _, week := range w.WorkWeeks {
totalHours += week.HoursWorked()
}
return totalHours
}
This code works just fine, but the duplication in WorkWeek.HoursWorked()
and WorkMonth.HoursWorked()
really grinds my gears. I tried to do the following, thinking I was very clever:
func (w WorkWeek) HoursWorked() time.Duration {
return sumHoursWorked(w.WorkDays)
}
func (m WorkMonth) HoursWorked() time.Duration {
return sumHoursWorked(m.WorkWeeks)
}
type countable interface {
HoursWorked() time.Duration
}
func sumHoursWorked(timeFrames []countable) time.Duration {
var totalHours time.Duration
for _, frame := range timeFrames {
totalHours += frame.HoursWorked()
}
return totalHours
}
However, as explained here, even though WorkDay
implements countable
, a slice of WorkDay
s does not count as a slice of countable
s.
So, is there some nifty, idiomatic way out of this situation that I'm missing, or am I just stuck with the duplication?
答案1
得分: 4
不。要么使用countables
的一部分来实现动态方法调度,或者进行一些编程(你的第一个解决方案),要么重新构建你的类型。我不了解你的问题领域,但是由周组成的月份似乎很奇怪,至少是月份/周的部分。
英文:
No. Either have a slice of countables
which gives you dynamic method dispatch or some programming (your first solution) or restructure your types. I have no idea of your problem domain but months consisting of weeks consisting of days seems odd, at least the month/week stuff.
答案2
得分: 2
不,因为countables
的切片是另一种类型。
你可以定义自己的切片类型,并将一个Add方法附加到它上面。
func (w WorkWeek) HoursWorked() time.Duration {
return sumHoursWorked(w.WorkDays)
}
func (m WorkMonth) HoursWorked() time.Duration {
return sumHoursWorked(m.WorkWeeks)
}
type countable interface {
HoursWorked() time.Duration
}
type SliceCountable []countable
func (m *SliceCountable) Add(c countable) {
*m = append(*m, c)
}
func (m SliceCountable) HoursWorked() time.Duration {
var totalHours time.Duration
for _, frame := range m {
totalHours += frame.HoursWorked()
}
return totalHours
}
func sumHoursWorked(timeFrames []countable) time.Duration {
var totalHours time.Duration
for _, frame := range timeFrames {
totalHours += frame.HoursWorked()
}
return totalHours
}
英文:
No because slice of countables
is another type.
You could define your own slice type and attach an Add method to it.
func (w WorkWeek) HoursWorked() time.Duration {
return sumHoursWorked(w.WorkDays)
}
func (m WorkMonth) HoursWorked() time.Duration {
return sumHoursWorked(m.WorkWeeks)
}
type countable interface {
HoursWorked() time.Duration
}
type SliceCountable []countable
func (m *SliceCountable) Add( c countable ) {
*m = append(*m, c )
}
func (m SliceCountable) HoursWorked() time.Duration {
var totalHours time.Duration
for _, frame := range m {
totalHours += frame.HoursWorked()
}
return totalHours
}
func sumHoursWorked(timeFrames []countable) time.Duration {
var totalHours time.Duration
for _, frame := range timeFrames {
totalHours += frame.HoursWorked()
}
return totalHours
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论