LeKSuS
LeKSuS

Reputation: 127

Dynamic conversion between generic interfaces of different types

Suppose I have following generic interface:

type Iface[T any] interface {
    MyFunc(T)
}

I would like to implement "adapter" or "converter" class, which helps to convert between interfaces of different types. Essentially, it wraps Iface[A] to behave like an Iface[B]:

type Adapter[A any, B any] interface {
    Adapt(Iface[A]) Iface[B]
}

So, I can't figure out how to write Adapt function:

type Iface[T any] interface {
    MyFunc(T)
}

type Adapter[A any, B any] interface {
    Adapt(Iface[A]) Iface[B]
}

type StringToIntAdapter struct {
}

func (StringToIntAdapter) Adapt(Iface[string]) Iface[Int] {
    // ???
}

I think I would need to somehow dynamically create a new instance of an interface inside of an adapter. But I can't find any tips out how to do so.

Upvotes: 0

Views: 96

Answers (1)

blackgreen
blackgreen

Reputation: 45081

An interface such as Iface[string] is implemented by types that declare a MyFunc(string) method. Similarly, Iface[int] is implemented by types that declare a MyFunc(int).

Your question, and your Adapt function, is equivalent to asking "how do I convert between a type that has a MyFunc(string) method to one that has a MyFunc(int)?".

In abstract, this is meaningless. Interfaces describe a behavior. To convert between interfaces, either the implementing type exhibits both behaviors or it doesn't.

If it exhibits both behaviors, e.g. the type has both a MyFunc(string) and a MyFunc(int) method, you can change one interface to another by asserting it.

var a Iface[string] = // ... assign some concrete value
var b Iface[int] = a.(Iface[int])

If the type does not exhibit both behaviors, the Adapt method as you defined cannot work. You have to specify how a type that implements Iface[T] can change its behavior to another Iface[U].

For example by defining an additional interface:

type Convertable[T, U any] interface {
    Iface[T]
    Convert() Iface[U]
}

func Adapt(v Convertable[string, int]) Iface[int] {
    return v.Convert()
}

This imposes that whatever type you pass to Adapt implements a method to change itself to the desired output interface. Each type will then have to specify its own logic by implementing Convert() Iface[U] method.

Upvotes: 0

Related Questions