英文:
Using a struct member as a member in another struct
问题
你好!以下是你要翻译的内容:
type (
A struct {
a string
}
B struct {
b *A.a
}
)
我得到了这个错误:
A.a未定义(类型A没有方法a)
我是否遗漏了什么?或者在Go语言中不允许这样做?
请注意,我只提供翻译服务,不会回答关于翻译内容的问题。如果你有其他问题,请告诉我。
英文:
type (
A struct {
a string
}
B struct {
b *A.a
}
)
I get this error:
A.a undefined (type A has no method a)
Am I missing something here? Or is it not allowed in Go?
答案1
得分: 4
当你定义一个结构体字段时,你需要指定它的名称和类型,就像你在结构体A.a
中所做的那样。但在结构体B
中:
b *A.a
*A.a
不是一个类型。
你不能在另一个结构体中嵌入一个结构体字段。请注意,你可以通过省略名称部分来嵌入一个完整的结构体,像这样:
type (
A struct {
a string
}
B struct {
A
}
)
结果是类型A
的所有字段和方法也将成为结构体B
的成员。如果你需要访问结构体B
中嵌入的结构体A
,你可以通过引用类型名称来访问它:
var b B
fmt.Println(b.A)
另一件你可以做的事情是在B
中有一个字段,它是一个指针,指向类型A
的现有值的字段:
B struct {
ap *string
}
a := A{a:"test"}
b := B{ap:&a.a} // B.ap将指向a.a
fmt.Println(*b.ap) // 输出 "test"
英文:
When you define a struct field, you have to specify its name and its type like you did with struct A.a
. But in struct B
:
b *A.a
*A.a
is not a type.
You can't embed a field of a struct
in another struct. Note that however you can embed complete structs in another by omitting the name part like this:
type (
A struct {
a string
}
B struct {
A
}
)
The result is that all the fields and methods of type A
will also be member of struct B
. If you need the embedded struct A
of B
, you can access it by referring to it as the type name:
var b B
fmt.Println(b.A)
Another thing you can do is have a field in B
which is a pointer and it points to the field of an existing value of type A
:
B struct {
ap *string
}
a := A{a:"test"}
b := B{ap:&a.a} // B.ap will point to a.a
fmt.Println(*b.ap) // Prints "test"
答案2
得分: 0
问题在于你将*A.a
作为字段b
的类型说明符。你唯一遗漏的是,你应该在那里使用b string
或b *string
(如果你至少想要在结构体B中有一个字符串字段)。
如果你的目标更像是“继承”字段,那么你应该在B中嵌入A,这将给B一个名为a
的属性。代码如下:
type B struct {
A
}
这是Go提供的最相似的继承构造。如果你在这里进行嵌入,你就可以这样做:
var instanceOfB = &B{}
fmt.Println(instanceOfB.a)
这在功能上等同于B从A继承(在这种情况下,这两个东西并不相同,行为在很多方面是不同的。我只是认为比较/对比继承是有帮助的)。在这一点上,你可以直接从B的实例中直接访问A的属性或方法。最好避免名称冲突,尽管它们不会导致编译错误。如果在嵌入类型之间或嵌入者和嵌入类型之间存在名称冲突,决定使用哪个方法/属性是在运行时进行的,我不确定解析规则是什么,但我认为你可以在语言规范中找到它们。
现在是我最后的想法...如果你的目标是从某个B的实例中引用A的a
属性,你只需要在B中包含一个字符串指针,并在实例化B时在构造函数或静态初始化器中将其设置为&A.a
。然而,这可能是一个不好的做法,因为它违背了封装的概念,而且很明显容易出错。
英文:
The problem is that you're using *A.a
as the type specifier for field b
. The only thing you're missing is that you should have b string
or b *string
there (if you want a string field in struct B at least).
Now if your goal is to do something more like 'inheriting' the field then you should embed A
in B
which will give B
a property called a
. That would look like this;
type B struct {
A
}
This is the most similar construct to inheritance Go offers. If you were to embed here you would be able to do something like;
var instanceOfB = &B{}
fmt.Println(instanceOfB.a)
Which is functionally equivalent of having B inherit from A (in this case, the two things are not the same though and behavior is different in many. I just think it's helpful to compare/contrast to inheritance). At this point you can access an property or method on A
directly from an instance of B
. It's best to avoid name collisions though they won't cause a compiler error. If you do have naming collisions between embedded types or the embeddor and an embedded type the decision of which method/property to use is made at runtime and I'm not sure what the resolution rules are but I think you can find them in the language spec.
Now my last idea... If your goal is to reference the a
property in an instance of A
from some instance of B
, you just want to include a sting pointer in B
and set it to &A.a
in your constructor a static initializer when you instantiate B
. However this is probably a bad practice as it defies the concept of encapsulation and is just very obviously error prone.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论