Понимание полиморфизма в го - PullRequest
0 голосов
/ 07 декабря 2018

Я думаю, что застрял в размышлениях о решении полиморфизма для моей следующей проблемы:

Допустим, у меня есть BaseTX struct с полями для транзакции.Теперь у меня есть два специальных типа транзакций: RewardTX struct и AllowanceTX struct.

RewardTX struct имеет на данный момент только состав BaseTX struct.

AllowanceTX struct имеет состав BaseTX struct и AddField.

Iтакже есть функция logicAndSaveTX(), которая имеет некоторую логику для полей из BaseTX, но в конце сериализует весь объект с использованием json.Marshal() и сохраняет byte[] где-то.

type TXapi interface {
    logicAndSaveTX()
}

type BaseTX struct {
    Field1 string
    Field2 string
}

type RewardTX struct {
    BaseTX 
}

type AllowanceTX struct {
    BaseTX 
    AddField string
}

func (tx BaseTX) logicAndSaveTX() {
    // logic on BaseTX fields; simplified:
    tx.Field1 = "overwritten"
    tx.Field2 = "logic done"

    // here would be marshal to json and save; simplified to print object:
    fmt.Printf("saved this object: %+v \n", tx)
}

func SaveTX(tx TXapi) {
    tx.logicAndSaveTX()
}


func main() {
    rewardTX := RewardTX{BaseTX : BaseTX{Field1: "Base info1", Field2: "Base info2"}}
    SaveTX(rewardTX) // should print rewardTX with fields from BaseTX
    allowanceTX := AllowanceTX{BaseTX : BaseTX{Field1: "Base info1", Field2: "Base info2"}, AddField: "additional field"}
    SaveTX(allowanceTX) // would like to print allowanceTX with fields from BaseTX + AdditionalField >>> instead only printing fields from BaseTX
}

https://play.golang.org/p/0Vu_YXktRIk

Я пытаюсь выяснить, как реализовать структуры и функции для работы с обоими типами транзакций, но в конце правильно сериализовать обе структуры.Моя проблема в том, что AddField не видно в моей текущей реализации.

Может быть, у меня здесь какой-то сбой мозга - я действительно хотел бы реализовать этот «правильный путь Go».:)

1 Ответ

0 голосов
/ 07 декабря 2018

Go не является объектно-ориентированным. Форма only полиморфизма в Go - это интерфейсы.

Исходить из других объектно-ориентированных языков может быть сложно,потому что вам нужно избавиться от множества идей, которые вы можете попытаться воплотить - например, «базовые» классы / типы.Просто удалите «базу» из вашего дизайнерского мышления;Вы пытаетесь превратить композицию в наследство, и это только доставит вам неприятности.

В этом случае, возможно, у вас есть законное обоснование для композиции здесь;у вас есть некоторые общие общие поля, используемые несколькими типами, но это не «базовый» тип.Это может быть «метаданные» или что-то в этом роде - я не могу сказать, как это назвать, учитывая, что ваш пример довольно абстрактный, но вы поняли.

Так что, возможно, у вас есть:

type TXapi interface {
    logicAndSaveTX()
}

type Metadata struct {
    Field1 string
    Field2 string
}

type RewardTX struct {
    Metadata 
}

func (tx RewardTX) logicAndSaveTX() {
    // logic on BaseTX fields; simplified:
    tx.Field1 = "overwritten"
    tx.Field2 = "logic done"

    // here would be marshal to json and save; simplified to print object:
    fmt.Printf("saved this object: %+v \n", tx)
}

type AllowanceTX struct {
    Metadata 
    AddField string
}

func (tx AllowanceTX) logicAndSaveTX() {
    // logic on BaseTX fields; simplified:
    tx.Field1 = "overwritten"
    tx.Field2 = "logic done"
    tx.AddField = "more stuff"

    // here would be marshal to json and save; simplified to print object:
    fmt.Printf("saved this object: %+v \n", tx)
}

Если обработка полей метаданных (или любых других) идентична во всех случаях использования, возможно, вы даете этому типу собственный метод logicTX для заполнения этих полей, который может вызываться logicAndSaveTX структур, которые его встраивают.

Ключевым моментом здесь является думать о поведении (методах) для типа, который будет ограничен этим типом , вместо того, чтобы думать о том, что он каким-то образом способен работать с "дочерними типами",Дочерние типы не существуют, и для типа, который является внедренным в другом типе, невозможно работать с его контейнером.

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