oop - 理解 Go 中的多态性
问题描述
我想我陷入了思考以下问题的多态性解决方案:
假设我有BaseTX struct
一个交易字段。现在我有两种特殊类型的交易:RewardTX struct
和AllowanceTX struct
.
RewardTX struct
此刻只有 的组成BaseTX struct
。
AllowanceTX struct
有BaseTX struct
和 的组成AddField
。
我还有一个函数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 方式”来实现它。:)
解决方案
Go 不是面向对象的。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
嵌入它的结构调用。
这里的关键是将类型上的行为(方法)考虑到该类型,而不是认为它能够以某种方式对“子类型”进行操作。子类型不存在,并且嵌入在另一种类型中的类型无法对其容器进行操作。
推荐阅读
- node.js - 如何在信使欢迎屏幕上添加按钮?
- django - Django websockets 身份验证
- android - 为什么我对一个包中的代码所做的更改没有反映在实际的应用程序中?
- java - 什么java数据结构适合像kafka这样的基于偏移量的单分区日志?
- c++ - 将类中声明的函数作为参数传递会导致编译错误
- apache-spark - 将带有纳秒的字符串转换为时间戳
- html - 带有 xsl 的 xpath:测试时
- c# - 使 8 x 8 网格具有正确的 FEN 表示法。像棋盘
- c++ - 在循环初始化中使用带有静态的 constexpr?
- android - Android Paging Library - 具有多种排序类型的数据+网络