Полиморфизм без методов в ходу - PullRequest
0 голосов
/ 21 февраля 2019

Примечание: я редактирую этот вопрос для конкретного примера того, почему я хочу это сделать, поэтому некоторые ответы могут больше не иметь смысла в контексте.

Я пишу немногокод, который передает данные от входа.Данные представлены в виде тегов, которые имеют идентификатор того, какие данные они содержат, а затем данные.

К сожалению, я не контролирую ввод и не знаю заранее, какие теги будут вэто, один может быть int, другой может быть строкой, а другой может быть массивом целых чисел.

Проблема возникает, когда мне нужно обработать все теги одного типа, например, если у меня есть фрагменттегов, функции, которая либо принимает, либо возвращает тег.

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

Интерфейсы, тем не менее, кажутся решениемздесь, и я хотел бы иметь Tag интерфейс для передачи, который требует, хотя я определяю методына них, и на самом деле нет никаких методов, которые им нужны.

Мое текущее решение выглядит следующим образом

type Tag interface{
    implementTag()
}

type TagInt int
func (tag TagInt) implementTag() {}

type TagString string
func (tag TagInt) implementTag() {}

Хотя это действительно работает и решает мою проблему, необходимость определения фиктивных методов только дляэто очень неправильно.

Итак, мой вопрос сводится к следующему: есть ли способ, которым я могу определить, что что-то является Tag без необходимости определения фиктивных методов?

Ответы [ 3 ]

0 голосов
/ 21 февраля 2019

А теперь хотите сделать срез, который может содержать как t1, так и t2, но ничего больше.

Вы не можете этого сделать.К сожалению.

0 голосов
/ 21 февраля 2019

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

if t1, ok := interfaceInput.(t1); !ok{
    // handle it being the wrong type here
    return
}

Также, если вы хотитетесная связь между типом данных и его методом, а именно объектом, что такого плохого в том, что он является методом объекта?

0 голосов
/ 21 февраля 2019

Вы можете использовать []interface{} для «слайса любого типа», но тогда вы можете использовать утверждения типа и / или переключатели типов, чтобы обнаружить фактические типы времени выполнения членов этого слайса.

Learnбольше о пустых интерфейсах в Tour of Go


А теперь хочу сделать срез, который может содержать как t1, так и t2, но ничего больше.

Это довольно необычное требование, и вряд ли оно понадобится вам в Go.Но вы также можете сделать свой собственный выборочный союз с помощью:

type item struct {
  typeSelector int
  t1Value t1
  t2Value t2
}

А затем используйте []item, проверяя typeSelector во время выполнения, чтобы увидеть, какое значение заполняется.

В качестве альтернативы вы можете дажеиспользуйте *t1 и *t2, а nil означают "нет значения в этом поле".

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