嵌入式结构方法是否有父/子的知识? [英] Can embedded struct method have knowledge of parent/child?

查看:87
本文介绍了嵌入式结构方法是否有父/子的知识?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在空闲时间一直和Go一起工作了几个月,我觉得我一直在徘徊。来自传统的面向对象程序设计语言,如Java和PHP,我很难把握组合和嵌入到Go中。我认为它最近最近点击了,并且想要更多地使用它,但是我为我的一个想法遇到了障碍。

假设我有一个包含Validate方法的结构体,并将其嵌入到当前正在工作的包中的结构体中。是否有方法我拥有这两个包),我可以得到一个对Validate方法中嵌入的结构的引用?有点像看到谁打电话给我的方式,因为我会在父母而不是嵌入式电话上调用它。



我会尝试将此可视化。 。

  type B struct {} 
func(b B)Validate(){
// get以某种方式参考A obj
}


类型A结构{
B
}

a:= A {B { }}
a.Validate()

我感觉好像这是不可能的,但如果可以的话,它会很酷。我想象你需要使A和B都是相同的接口类型才能工作。任何想法或帮助将不胜感激。

解决方案

这是不可能的。为了更好地理解原因,请参阅您的示例的稍微修改后的版本:

  type B struct {} 

func(b * B)Validate(){
fmt.Printf(b:%p \ n,b)
}

type A struct {



$ b func main(){
b:= B {}
a1:= A {& b}
a2: = A {& b}

a1.Validate()
a2.Validate()
a1.B.Validate()
a2.B.Validate( )

b.Validate()
}

输出为预计,相同的值 * B 无处不在( Go Playground ):

  b:0x1becd8 
b:0x1becd8
b:0x1becd8
b :0x1becd8
b:0x1becd8

正如您所看到的,我更改了方法receiver和embedded键入指针 B



从这个例子中可以清楚地看出:您可以使用相同的值 B B )相同的地址嵌入到 A



您可以在两者上调用 Validate():所以理论上的父甚至不是常量给定值 * B 这不会成为交易断路器,但是:具有 A的值,您可以通过编写 a.Validate()来调用升级方法 B.Validate() c>这是可以的,但你也可以称它为 aBValidate() - 现在这个时候你并不真正具有 A的值对 * B 值调用(可争论的,但是 Validate(),而不是 A ),但最后你也可以调用 b.Validate() - 这次你肯定没有值 A



父类没有明确的类型, B (或 * B )可以嵌入到任何类型中(所以它不能是



所以image:你有一个具体的值 * B 当它的 Validate()方法被调用时,有时候会有一个父类,有时候不会有。那么有什么理由要有父母?



回到你的例子:对于这个 Validate()方法来验证有意义的东西,它应该(必须)作为一个参数传递给 Validate()方法 - 明确而不是自动地。



您可以做的最好的是captncraig在他的回答(+1)中写的内容。 p>

你可以简化一点,但如果你明确地向 A 添加一个方法,它会调用 B.Validate()像这样:

  func(a * A)Validate2(){
a.Validate(a)
}

//使用它:
.Validate2()

没有理由将您想象的验证器嵌入到 A 中,它应该只是是 A 的字段,或者由于没有直接关系,它可以是一个独立的验证器。在这两种情况下,如果你想简化验证,你可以为 A 添加一个帮助器 Validate()方法。

I have been working with Go on and off on my free time for a few months and I feel I've been getting a hang of it. Coming from traditional OOP languages, such as Java and PHP, I had a hard time grasping composition and embedding in Go. I think it finally clicked recently and want to use it more, but I have hit a roadblock for one idea I have.

Lets say I have a struct from a package that has a Validate method and I embedded that in my struct in the package I am currently working in. Is there a way (I own both packages) that I can get a reference to the struct that is doing the embedding inside of the Validate method? Kind of like a way to see who called me since I would be calling it on the "parent" instead of the embedded.

I'll try to visualize this...

type B struct {}
func (b B) Validate() {
  // get reference somehow of A obj
}


type A struct {
  B
}

a := A{B{}}
a.Validate()

I feel as though this isn't possible, but it would be cool if you could. I'd imagine that you would need to make A and B both the same interface type for this to work. Any thoughts or help will be much appreciated.

解决方案

This is something not possible. To better understand why, see this slightly modified version of your example:

type B struct{}

func (b *B) Validate() {
    fmt.Printf("b:%p\n", b)
}

type A struct {
    *B
}

func main() {
    b := B{}
    a1 := A{&b}
    a2 := A{&b}

    a1.Validate()
    a2.Validate()
    a1.B.Validate()
    a2.B.Validate()

    b.Validate()
}

Output as expected, the same value of *B everywhere (Go Playground):

b: 0x1becd8
b: 0x1becd8
b: 0x1becd8
b: 0x1becd8
b: 0x1becd8

As you can see, I changed the method receiver and the embedded type to pointer of B.

From this example it is clear: you can use the same value of B (or rather the same address of a value of B) to embed in different values of type A!

And you can call Validate() on both: so the theoretical "parent" is not even "constant" for a given value of *B. This wouldn't be a deal-breaker, but: having a value of A, you can call the promoted method B.Validate() by writing a.Validate() which is OK, but you can also call it like a.B.Validate() - now this time you don't really have a value of A (arguable, but Validate() is called on a value of *B and not A), but finally you can also call b.Validate() - this time you definitely don't have a value of A.

There is no definite type for the parent, B (or *B) can be embedded in any type (so it couldn't be anything other than interface{}).

So image: you have a concrete value of *B and when its Validate() method is called, sometimes there is a parent, and sometimes there isn't. Then what would be the justification to have a parent at all?

Back to your example: for this Validate() method to validate something meaningful, it should (must) be passed to the Validate() method as a parameter - explicitly and not automatically.

The best you can do is what captncraig wrote in his answer (+1).

You can simplify it a little though if you explicitly add a method to A which would call B.Validate() like this:

func (a *A) Validate2() {
    a.Validate(a)
}

// And using it:
a.Validate2()

There is no justification for a validator of the kind you imagine to be embedded in A, it should just be a field of A, or since there is no direct relation, it can be an "independent" validator. In both of these cases you may add a helper Validate() method to A if you would like to simplify validation.

这篇关于嵌入式结构方法是否有父/子的知识?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆