Как мне объявить интерфейс, у которого есть метод для возврата фрагмента другого интерфейса? - PullRequest
2 голосов
/ 09 марта 2019

Вот пример, который я создал, где я объявляю свою первую структуру, которая является Toolbox, которая содержит срез Hammers. Я сделал интерфейс для Toolbox и Hammer, чтобы другие могли использовать мои функции без необходимости использовать мои структуры, если они следуют реализации моего интерфейса.

package main

import "fmt"

type ToolboxInterface interface {
    GetHammers() []HammerInterface
}

type HammerInterface interface {

}

type Toolbox struct {
    Hammers []Hammer
}

func (t Toolbox)GetHammers() []HammerInterface  {
    return []HammerInterface{t.Hammers}
}

type Hammer struct {
    Color string
}

func CountHammersInToolbox(t ToolboxInterface) int {
    hammers := t.GetHammers()
    return len(hammers)
}

func main()  {
    toolbox := Toolbox{Hammers: []Hammer{
        {Color: "Red"},
        {Color: "Blue"},
        {Color: "Green"}}}

    fmt.Println(len(toolbox.Hammers))

    fmt.Println(CountHammersInToolbox(toolbox))
}

My ToolboxInterface объявляет метод GetHammers(), который я реализовал. Однако метод CountHammersInToolbox возвращает 1 вместо 3, как показано в выводе.

uberswe$ go run scratch/main.go 
3
1

Я пробовал разные варианты этого, но чувствую себя немного застрявшим. Я не понимаю, почему он возвращает 1, но я подозреваю, что я неправильно объявляю свой метод интерфейса.

Как мне объявить интерфейс, у которого есть метод для возврата фрагмента другого интерфейса?

1 Ответ

5 голосов
/ 09 марта 2019

Нет ничего плохого в ваших определениях интерфейса.Проблема в том, что вы неправильно конвертируете []Hammer в []HammerInterface.Похоже, что вы ожидаете, что это произойдет волшебным образом, но это не так.

В этом фрагменте кода:

func (t Toolbox) GetHammers() []HammerInterface  {
    return []HammerInterface{t.Hammers}
}

Вы, вероятно, ожидаете, что возвращаемый результат является частью3 HammerInterface с, но вместо этого вы получаете один HammerInterface, который на самом деле представляет собой срез из трех Hammers с.

Это преобразование необходимо выполнить вручную.См. этот пост для получения более подробной информации.

func (t Toolbox) GetHammers() []HammerInterface  {
    hammerInterfaces := make([]HammerInterface, len(t.Hammers))
    for i, hammer := range t.Hammers {
        hammerInterfaces[i] = t.Hammers[i]
    }
    return hammerInterfaces
}

В большинстве реальных сценариев ваша ошибка будет обнаружена компилятором, потому что ваш кусок молотков (t.Hammers) не будетудовлетворяет интерфейсу HammerInterface, но в вашем случае, поскольку этот интерфейс пуст, он соответствует любому типу , как interface{}.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...