Создайте две структуры, которые отличаются реализацией одного метода

#go

#Вперед

Вопрос:

Я хочу создать минимальную и максимальную кучу целых чисел:

 package main

import (
    "container/heap"
    "fmt"
)

func main() {

    hi := make(IntHeap, 0)
    for number := 10; number >= 0; number-- {
        hi = append(hi, number)
    }
    heap.Init(amp;hi)
    fmt.Println(heap.Pop(amp;hi))
    fmt.Println(heap.Pop(amp;hi))
    fmt.Println(heap.Pop(amp;hi))
}

// An IntHeap is a min-heap of ints.
type IntHeap []int

func (h IntHeap) Len() int           { return len(h) }
func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h IntHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }

func (h *IntHeap) Push(x interface{}) {
    *h = append(*h, x.(int))
}

func (h *IntHeap) Pop() interface{} {
    old := *h
    n := len(old)
    x := old[n-1]
    *h = old[0 : n-1]
    return x
}

type IntMaxHeap IntHeap

func (h IntMaxHeap) Less(i, j int) bool { return h[i] > h[j] }
  

Если я хочу использовать IntMaxHeap вместо этого, я получаю:

 ./median_stream.go:14: cannot use amp;hi (type *IntMaxHeap) as type heap.Interface in function argument:
        *IntMaxHeap does not implement heap.Interface (missing Len method)
./median_stream.go:15: cannot use amp;hi (type *IntMaxHeap) as type heap.Interface in function argument:
        *IntMaxHeap does not implement heap.Interface (missing Len method)
./median_stream.go:16: cannot use amp;hi (type *IntMaxHeap) as type heap.Interface in function argument:
        *IntMaxHeap does not implement heap.Interface (missing Len method)
./median_stream.go:17: cannot use amp;hi (type *IntMaxHeap) as type heap.Interface in function argument:
        *IntMaxHeap does not implement heap.Interface (missing Len method)
  

Как я могу создать две структуры («классы»), которые отличаются только одной реализацией метода? Рабочая версия должна печатать 3 самых больших числа из кучи.

Ответ №1:

Когда вы объявляете новый тип в Go, он не наследует методы базового типа. Если вы хотите наследовать методы, рассмотрите возможность использования композиции:

 type IntMaxHeap struct {
    IntHeap
}

func (h IntMaxHeap) Less(i, j int) bool { return h.IntHeap[i] > h.IntHeap[j] }
  

Если у вас есть загрунтованный IntHeap (или любой []int фрагмент, если на то пошло), вы можете создать этот тип IntMaxHeap{slice} без необходимости переопределения других методов.

Этот шаблон может быть весьма полезен для объявления нескольких порядков для использования с sort пакетом без дублирования методов.

Ответ №2:

Короткий ответ: вы не можете. Go не имеет наследования метода. Самое короткое, что вы могли бы получить, — это использовать анонимные поля (см. Спецификацию о типах структур), но вы потеряете механику среза.

Вам придется повторно реализовать интерфейс для каждого типа. Но вы можете сделать это разумно, используя неэкспортируемую функцию для выполнения задания и просто возвращая результат этой функции. Это может сэкономить вам немного времени на вводе текста и обеспечить, чтобы ваши методы имели одинаковую внутреннюю работу.

Пример:

 type A []int

func (a A) Len() int {
    return getLen(a)
}

type B []int

func (b B) Len() int {
    return getLen(a)
}

func getLen(slice []int) int {
    return len(slice)
}
  

Очевидно, что мой пример глуп, потому что я просто оборачиваю len встроенное, но для более длинных функций (скажем, кроме oneliners) это весьма полезно.