嵌入式结构方法可以了解父/子吗? [英] Can embedded struct method have knowledge of parent/child?
问题描述
我在空闲时间断断续续地工作了几个月,我觉得我已经掌握了它.来自 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屋!