如果结构体A嵌入在B中,A的方法能够访问B的方法和字段吗?

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

If struct A is embedded in B, can methods on A access method and fields of B?

问题

<!-- language: lang-go -->

struct A {}

func (a *A) BName(id int) string {
   return a.Name
}

struct B {
   *A
   Name string
}

func main() {
   b := &B{Name: "abc"}
   fmt.Println(b.Name)
}

这段代码出错了,我想知道如何编写代码来实现 A.BName 可以访问 B 结构体的属性 Name。

英文:

<!-- language: lang-go -->

  struct A {}

  func (a *A) BName(id int) string {
     return a.Name
  }

  struct B {
     *A
     Name string
  }

  func main() {
     b := &amp;B{Name: &quot;abc&quot;}
     fmt.Println(b.Name)
  }

the code failure, I want know how to write code to achieve, A.BName can access B struct attribute Name

答案1

得分: 6

这是不可能的。结构体A对于它嵌入的类型一无所知。想一想,A可以嵌入到任何其他结构体中,所以你怎么能提前知道A嵌入的结构体的类型呢?

如果你想要实现这个,你需要在A中放置对外部结构体B的引用。

type A struct {
    *B 
}

func (a *A) PrintName() string { return a.B.Name }

type B struct {
    A // 这里不需要使用指针
    Name string
}

var b B
b.A.B = &b

fmt.Println(b.PrintName())
英文:

This is not possible. struct A does not know anything about the types it is embedded into. Think about it, A can be embedded into any other struct, so how could you know ahead of time the type of the struct that A is embedded into.

If you want to do this, you need to place a reference to B, the outer structure into A.

type A struct {
    *B 
}

func (a *A) PrintName() string { return a.B.Name }

type B struct {
    A // no need to use a pointer here
    Name string
}

var b B
b.A.B = &amp;b

fmt.Println(b.PrintName())

答案2

得分: 1

A访问B让我想起了一种is-a关系,其中A“是一个”B

文章“Go是面向对象的语言吗?”确实指出Go中没有真正的子类型

  • 如果它真的是子类型,那么匿名字段将导致外部类型变为内部类型。在Go中,情况并非如此。这两种类型仍然是不同的。
  • 可以像访问嵌入字段一样访问匿名字段。

示例:

package main

type A struct{
    // 对B一无所知
}

type B struct {
    A  // B是A的一种
}

func (a *A) f() { fmt.Println("A.f") }
func (b *B) f() { fmt.Println("B.f") }

func save(A) {
    // 做一些事情
}

func main() {
    b := B
    save(&b)  // 哎呀!b不是A
    b.f()     // B.f()
    b.A.f()   // A.f()
}

> 多重继承的一个问题是,当多个父类上存在相同方法时,语言通常不明显,有时甚至是模棱两可的,不知道使用哪个方法。
>
> 在Go中,您始终可以通过与类型同名的属性访问各个方法。
>
> 实际上,当您使用匿名字段时,Go会创建一个与您的类型同名的访问器。

这就是“b.A”的含义:一个对匿名字段的访问器。

英文:

A accessing B reminds me of a is-a relationship, where A "is-a" B.

The article "Is Go an Object Oriented language?" does note that there is no true subtyping in Go:

  • if it was truly subtyping then the anonymous field would cause the outer type to become the inner type. In Go this is simply not the case. The two types remain distinct.
  • The anonymous fields are still accessible as if they were embedded

Example:

package main

type A struct{
    // doesn&#39;t know anything about B
}

type B struct {
    A  //B is-a A
}

func (a *A) f() { fmt.Println(&quot;A.f&quot;) }
func (b *B) f() { fmt.Println(&quot;B.f&quot;) }

func save(A) {
    //do something
}

func main() {
    b := B
    save(&amp;b)  //OOOPS! b IS NOT A
    b.f()     // B.f()
    b.A.f()   // A.f()
}

> One of the issues with multiple inheritance is that languages are often non obvious and sometimes even ambiguous as to which methods are used when identical methods exist on more than one parent class.
>
> With Go you can always access the individual methods through a property which has the same name as the type.
>
> In reality when you are using Anonymous fields, Go is creating an accessor with the same name as your type.

That is what "b.A" is: an accessor to an anonymous field..

huangapple
  • 本文由 发表于 2014年9月4日 18:06:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/25662684.html
匿名

发表评论

匿名网友

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

确定