Я пытаюсь использовать шаблоны компоновщика (заимствовано из Java), чтобы структуры могли реализовывать интерфейсы. Например, в идеале мне хотелось бы такой кодовый шаблон:
package main
import "fmt"
type Oner interface {
One() int
}
type Twoer interface {
Two() int
}
func main() {
s := NewObject().
WithOne(1).
Build()
_, ok := s.(Oner)
fmt.Println(ok) // Prints true
_, ok = s.(Twoer)
fmt.Println(ok) // Prints false
t := NewObject().
WithOne(1).
WithTwo(2).
Build()
_, ok = t.(Oner)
fmt.Println(ok) // Prints true
_, ok = t.(Twoer)
fmt.Println(ok) // Prints true
}
Как вы могли видеть, определение компоновщика определяет, какие интерфейсы s
и t
реализуют.
Как можно написать определение функции построителя NewObject()
, чтобы метод Build()
возвращал структуру, которая может (возможно) реализовать Oner
и Twoer
?
Edit:
Вот некоторые пояснения о том, как это будет использоваться. Я создаю библиотеку, которая запрещает передачу определенных структур в функции, если они нарушают безопасность типов. Например:
type Oner interface {
One() int
}
type OneAndTwoer interface {
Oner
Two() int
}
type Library interface {
DoSomethingWithOner(Oner)
DoSomethingWithOneAndTwoer(Twoer)
}
Хотя мы можем определить функцию, которая всегда создает OneAndTwoer
, мои ограничения заключаются в том, что всякий раз, когда мы создаем OneAndTwoer
, это занимает намного больше времени, чем простое построение Oner
func NewOneAndTwoer() OneAndTwoer {
// Do some really really complicated logic which takes a lot of time
}
func NewOner() Oner {
// Do simple logic
}
Вы могли бы представить, как, если у нас есть Threer
, Fourer
и т. Д., Это становится чрезвычайно громоздким, и мы должны конструировать конструкторы для всех возможных перестановок атрибутов.
Здесь пригодятся шаблоны для строителей. Предполагая, что вычисления для One
, Two
и т. Д. Не зависят друг от друга, мы можем выбрать, какой интерфейс мы хотим создать.