子类型中的超类型

时间:2017-05-03 20:39:22

标签: go

来自OOP范例并从OOP语言移植代码,我遇到了一个问题,现在通过抽象在OOP中解决了所以我想知道如何在Go中解决以下问题,而不是在继承。

在这种情况下,我的ValueObjects(DTO,POJO等)由其他ValueObject组成。我通过返回json的Web服务调用来填充它们,所以基本上我的函数/方法调用对于所有类型和子类型都是通用的。

我的超级类型EntityVO

type EntityVO struct {
    EntityName    string
    EntityType    string
    PublicationId string
    Version       string
}

由EntityVO

组成的子类型1
type 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子类型中,可以将子类型传递给接受超类型但不在其中的函数,因此想知道应该如何进行,所以我不会仅仅签署仅在签名方面不同的重复代码?

在这种情况下有什么建议可以采用更好的方法吗?

2 个答案:

答案 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{}类型。我认为类似的方法适用于您的情况。

  1. 定义用于存储每个实体可能不同的Web服务属性的数据类型,例如

    type ServiceDescriptor struct {
      URI string
      //other field/properties...
    }
    
  2. 填充实体的功能可能类似于

    func RequestList(desc *ServiceDescriptor, v interface{}) error {
        //Retrieve json data from web service
        //some code
    
        return json.Unmarshal(data, v)
    }
    
  3. 您可以调用该函数来填充不同类型的实体,例如

    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)