LoginSignup
0
0

More than 5 years have passed since last update.

enum値を引数に持つメソッドを持つstructのInterfaceを作るコツ

Posted at

golangではライブラリ自体はinterfaceを提供しておらず、使う側で必要になったら作れという風潮があると思ってます。golangのinterfaceはダックタイプなので、概ねはそれで上手く行きます。

ただ、引数にenum値がある場合、素直にメソッドのシグネチャをコピペするとinterface自体が実装に依存してしまうので一工夫が必要です。

やってることはinterfaceにも同じenumを作りましょうというだけなのでなんということはないのですが、DIとかに慣れてない人はちょっと嵌りそうな気がします。

実装例は以下です。参考になれば幸いです。


package main

import "fmt"

// 例えば、以下のようなinterface化したいライブラリ(?)があったとする。

type Hoge struct {
    a int
}

type Mode int

const (
    ModeOne = iota
    ModeTwo
)

func NewHoge(a int) *Hoge {
    return &Hoge{a: a}
}

func (h Hoge) Mul(m Mode) int {
    return h.a * int(m)
}

// ここから下はインターフェース

type MulerMode int

const (
    MulerModeOne = iota
    MulerModeTwo
)

// 普通にやるとMulの引数の型にModeを指定してしまうが、そうするとInterfaceが実装に依存してしまう
// ここでは同じ値域のenum、MulerModeをinterfaceとセットで用意して回避する
type Muler interface {
    Mul(m MulerMode) int
}

// ここから下はインターフェースを通じてHogeを使いたい場合

type MulerImpl struct {
    Hoge
}

func NewMulerImpl(a int) *MulerImpl {
    return &MulerImpl{Hoge: Hoge{a: a}}
}

func (m *MulerImpl) Mul(mm MulerMode) int {
    var md Mode // ここでenum同士のマッピングをする
    switch mm {
    case MulerModeOne:
        md = ModeOne
    case MulerModeTwo:
        md = ModeTwo
    default:
        return 0 // 本当はエラーとかだと思う
    }
    return m.Hoge.Mul(md)
}

// 実際に呼び出す

func main() {
    var m Muler
    m = NewMulerImpl(1)
    fmt.Print(m.Mul(MulerModeOne))
}

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0