使用父级

时间:2017-08-27 20:46:19

标签: go methods types override type-safety

我必须定期调用父结构的方法,但是在调用时,它必须更新嵌入式结构的唯一扩展属性(在我的例子中,结构具有不同的id数据类型)。

我能想到的唯一解决方案是覆盖父结构的方法,以便在再次调用periodic方法时,它使用嵌入结构的方法而不是父结构的方法。

代码如下:

package main

import (
    "fmt"
)

type Fruit struct {
    image *Image
    tree  *Tree

    SetImage func(*Image)
    SetTree  func(*Tree) // #2 (always nil for Strawberry)
}

func NewFruit() *Fruit {
    f := &Fruit{}
    f.SetImage = f.setImage
    f.SetTree = f.setTree
    return f
}

func (f *Fruit) Image() *Image {
    return f.image
}
func (f *Fruit) Tree() *Tree {
    return f.tree
}

func (f *Fruit) setImage(i *Image) {
    f.image = i
}
func (f *Fruit) setTree(t *Tree) {
    f.tree = t
}

type Strawberry struct {
    *Fruit
    id int
}

func NewStrawberry(f *Fruit) *Strawberry {
    strawberry := &Strawberry{Fruit: f}
    return strawberry
}
func (s *Strawberry) SetID(i int) {
    s.id = i
}
func (s *Strawberry) ID() int {
    return s.id
}
func (s *Strawberry) setImage(i *Image) {
    s.id = 6
    s.image = i
}

type Kiwi struct {
    *Fruit
    id string
}

func NewKiwi(f *Fruit) *Kiwi {
    kiwi := &Kiwi{Fruit: f}
    return kiwi
}
func (k *Kiwi) SetID(i string) {
    k.id = i
}

func (k *Kiwi) ID() string {
    return k.id
}
func (k *Kiwi) setImage(i *Image) {
    k.id = "abc"
    k.image = i
}
func (k *Kiwi) setTree(t *Tree) {
    k.tree = t
}

type Image struct {
    path string
}

type Tree struct {
    height int
}

func main() {
    f := NewFruit()
    f.SetImage(&Image{"kiwi1.jpg"})

    /*s := NewStrawberry(f)
    s.SetImage = s.setImage
    fmt.Println(s, s.ID(), s.Image())
    f.SetImage(&Image{"strawberry.jpg"})
    fmt.Println(s, s.ID(), s.Image())*/

    k := NewKiwi(f)
    k.SetImage = k.setImage
    k.SetTree = k.setTree
    fmt.Println(k, k.ID(), k.Image())
    f.SetImage(&Image{"kiwi2.jpg"})
    f.SetTree(&Tree{2})
    fmt.Println(k, k.ID(), k.Image(), k.Tree())
}

虽然上面的代码确实有效,但是当父结构Fruit需要时,我有两个问题。使用所需SetXXX(*XXX)方法的其他10个属性:

  1. 然后必须更新所有嵌入的结构以反映新的父结构方法。对于每个属性来说,这似乎是很多必要的编码。

  2. 其中一些嵌入式结构不需要所有属性方法,只留下一些nil。一个很好的例子,并非所有水果都生长在树上。将评论#2中的财产留给Strawberry无用。

  3. 这些问题是否都有效,是否有办法避免这些问题?

    P.S。 该应用程序需要大量的操作吞吐量,因此理想情况下,代码应该是类型安全且最佳的,而不使用反射和类型断言的过度使用(不能使每个属性interface{})。

1 个答案:

答案 0 :(得分:2)

  

这些问题是否都有效,是否有办法避免这些问题?

不,是的。

只需编写惯用的GO并执行而不是尝试在Go中编写传统的OO。例如。在Set中,Setters和Getters并不常见。并且不再考虑嵌入作为父/子关系。