2017-08-27 120 views
-2

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

我能想到的唯一解决方案是重写父结构的方法,以便在再次调用周期性方法时,它使用嵌入结构的方法而不是父母的原始结构。

的代码如下:

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没用。

这两个问题都有效,有没有办法避免它们?

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

回答

2

这两个问题都是有效的,有没有办法避免它们?

没有,是的。

只要写出惯用的GO并且做不是尝试在Go中写传统的OO。例如。 Go中不常见Setter和Getter。并且不要想到嵌入作为父母/孩子的关系。

+0

我不明白它如何写得不同(惯用的Go方式)。你能否提供一个解决我问题第一句中提到的问题的反例。 由于缺乏一个更好的单词,我使用了“父母”。 –

+1

@FanusduToit你写了“所有的嵌入式结构必须更新以反映新的父结构方法”,这是错误的。结构嵌入促进方法。如果嵌入类型有一个方法,那么嵌入类型的方法集通过这种方法得到了增强(给出了一些技术细节)。只要摆脱这种无意义的Setters并阅读https://golang.org/ref/spec#Struct_types,重点关注方法集。 – Volker

+1

你最近的评论比最初的答案要好得多。我现在明白了为什么我的'setters'是无用的,因为你实际上帮助我理解了为什么。谢谢! –