嵌入式结构方法可以了解父/子吗? [英] Can embedded struct method have knowledge of parent/child?

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

问题描述

我在空闲时间断断续续地工作了几个月,我觉得我已经掌握了它.来自 Java 和 PHP 等传统 OOP 语言,我很难掌握 Go 中的组合和嵌入.我认为它最近终于被点击并想要更多地使用它,但我的一个想法遇到了障碍.

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.

假设我有一个来自一个包的结构,它有一个 Validate 方法,我将它嵌入到我当前正在使用的包中的结构中.有没有办法(我拥有两个包)可以引用在 Validate 方法内部进行嵌入的结构?有点像查看谁给我打电话的方式,因为我会在父"而不是嵌入式上调用它.

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()

我觉得这似乎是不可能的,但如果可以的话就太好了.我想您需要使 A 和 B 都具有相同的接口类型才能使其工作.任何想法或帮助将不胜感激.

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
", 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):

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

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

如您所见,我将方法接收器和嵌入类型更改为 B 的指针.

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

从这个例子中可以清楚地看出:您可以使用 B 的相同值(或者 B 的值的相同地址)来嵌入不同的值输入 A!

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!

并且您可以在两者上调用 Validate():因此对于 *B 的给定值,理论上的父级"甚至不是常数". 这不会破坏交易,但是:如果值为 A,您可以通过编写 B.Validate() 调用提升的方法 B.Validate()code>a.Validate() 这没问题,但你也可以像 aBValidate() 一样调用它——现在你真的没有 A 的值(有争议,但 Validate() 是在 *B 而不是 A 的值上调用的),但最后你也可以调用 b.Validate() - 这次你肯定没有 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.

父类没有明确的类型,B(或*B)可以嵌入到任何类型中(所以它不能是除了接口{}).

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{}).

所以形象:你有一个 *B 的具体值,当它的 Validate() 方法被调用时,有时有一个父级,有时没有.那么拥有父母的理由是什么?

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?

回到你的例子:对于这个 Validate() 方法来验证有意义的东西,它应该(必须)作为参数传递给 Validate() 方法 -显式而非自动.

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.

你能做的最好的事情就是 captncraig 在他的回答 (+1) 中所写的内容.

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

如果你显式地向 A 添加一个方法,它会像这样调用 B.Validate() ,你可以稍微简化一下:

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()

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

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天全站免登陆