在另一个结构体中使用结构体成员作为成员。

huangapple go评论78阅读模式
英文:

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 stringb *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.

huangapple
  • 本文由 发表于 2015年4月13日 13:00:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/29598131.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定