来自OOP范例并从OOP语言移植代码,我遇到了一个问题,现在通过抽象在OOP中解决了所以我想知道如何在Go中解决以下问题,而不是在继承。
在这种情况下,我的ValueObjects(DTO,POJO等)由其他ValueObject组成。我通过返回json的Web服务调用来填充它们,所以基本上我的函数/方法调用对于所有类型和子类型都是通用的。
我的超级类型EntityVO
type EntityVO struct {
EntityName string
EntityType string
PublicationId string
Version string
}
由EntityVO
组成的子类型1type ArticleVO struct {
EntityVO
ContentSize string
Created string
}
子类型2由EntityVO组成,它拥有自己唯一的字段集
type CollectionVO struct {
EntityVO
ProductId string
Position string
}
我正在调用Web服务来检索数据并填充这些VO。
之前我有一个函数可以调用Web服务并填充数据,但现在我复制了每个VO的代码。
type Article struct{}
func (a *Article) RequestList(articleVO *valueObject.ArticleVO) (*valueObject.ArticleVO, error) {
// some code
}
复制相同的代码但更改签名。
type Collection struct{}
func (c * Collection) RequestList(collectionVO *valueObject.CollectionVO) (*valueObject.ArticleVO, error) {
// some code - duplicate same as above except method signature
}
我和几个实体只是因为我的VO不同而我被迫复制代码并迎合每种类型的VO我。在OOP子类型中,可以将子类型传递给接受超类型但不在其中的函数,因此想知道应该如何进行,所以我不会仅仅签署仅在签名方面不同的重复代码?
在这种情况下有什么建议可以采用更好的方法吗?
答案 0 :(得分:2)
这是golang界面可以发光的地方。
但值得注意的是,在golang中编写子类/继承代码很困难。我们宁愿将其视为构图。
type EntityVO interface {
GetName() string
SetName(string) error
GetType() string
...
}
type EntityVOImpl struct {
EntityName string
EntityType string
PublicationId string
Version string
}
func (e EntityVOImpl) GetName() string {
return e.EntityName
}
...
type ArticleVOImpl struct {
EntityVOImpl
ContentSize string
Created string
}
type CollectionVOImpl struct {
EntityVO
ProductId string
Position string
}
// CODE
func (e *Entity) RequestList(entityVO valueObject.EntityVO) (valueObject.EntityVO, error) {
// some code
}
此外,只要你的界面文件是共享的,我认为通过网络发送/编组/解组结构不会有任何问题。
答案 1 :(得分:1)
json.Unmarshal
的第二个参数是"通用" interface{}
类型。我认为类似的方法适用于您的情况。
定义用于存储每个实体可能不同的Web服务属性的数据类型,例如
type ServiceDescriptor struct {
URI string
//other field/properties...
}
填充实体的功能可能类似于
func RequestList(desc *ServiceDescriptor, v interface{}) error {
//Retrieve json data from web service
//some code
return json.Unmarshal(data, v)
}
您可以调用该函数来填充不同类型的实体,例如
desc := &ServiceDescriptor{}
article := ArticleVO{}
desc.URI = "article.uri"
//...
//You must pass pointer to entity for 2nd param
RequestList(desc, &article)
collection := CollectionVO{}
desc.URI = "collection.uri"
//...
//You must pass pointer to entity for 2nd param
RequestList(desc, &collection)