在实现接口时,无法访问结构体上定义的公共属性。

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

Defined public properties on a struct can not be accessed implementing interface

问题

有一个接口Comment,必须实现才能被包功能访问。尽管实现了接口并创建了一个CommentTest对象的切片,但是将Comment作为项类型,使得Title属性无法访问。PS:在这种情况下,Stringer函数可以正常工作。有没有一种方法可以在不进行类型断言的情况下使其工作?

package main

import "fmt"

type Comment interface {
	SetChild(Comment)
	GetChildren() []Comment
	GetID() int
	GetParentID() int
}

type CommentTest struct {
	Title    string
	ID       int
	ParentID int
	Children []Comment
}

func (ct *CommentTest) SetChild(c Comment) {
	ct.Children = append(ct.Children, c)
}

func (ct CommentTest) GetChildren() []Comment {
	return ct.Children
}

func (ct CommentTest) GetID() int {
	return ct.ID
}

func (ct CommentTest) GetParentID() int {
	return ct.ParentID
}

// works well, all public properties are 100% accesible
func (ct CommentTest) String() string {
	return "{ID: " + strconv.Itoa(ct.ID) + ", ParentID: " + strconv.Itoa(ct.ParentID) + ", Title: " + ct.Title + "}"
}

/*
	There are test comments with this structure:

		1 ->
			2 ->
				4
			3 ->
				5
*/
func testData() (Comment, []Comment) {
	var plain []Comment

	root := &CommentTest{ID: 1, ParentID: 3, Title: "Test 1"} // ParentID 3 -> Check for infinite recursion

	plain = append(plain, root)
	plain = append(plain, &CommentTest{ID: 2, ParentID: 1, Title: "Test 2"})
	plain = append(plain, &CommentTest{ID: 3, ParentID: 1, Title: "Test 3"})
	plain = append(plain, &CommentTest{ID: 4, ParentID: 2, Title: "Test 4"})
	plain = append(plain, &CommentTest{ID: 5, ParentID: 3, Title: "Test 5"})

	return root, plain
}

func main() {
	root, plain := testData()

	fmt.Println(root) // works well

	root.Title //root.Title undefined (type Comment has no field or method Title)
}
英文:

There is an interface Comment that has to be implemented in order to be accessible by a package functionality. Though implementing the interface and then making a slice of CommentTest objects but with Comment as items type makes the Title public property undefined. PS: Stringer works fine in this case. Is there a way to make it work without type assertion?

package main
import "fmt"
type Comment interface {
SetChild(Comment)
GetChildren() []Comment
GetID() int
GetParentID() int
}
type CommentTest struct {
Title string
ID int
ParentID int
Children []Comment
}
func (ct *CommentTest) SetChild(c Comment) {
ct.Children = append(ct.Children, c)
}
func (ct CommentTest) GetChildren() []Comment {
return ct.Children
}
func (ct CommentTest) GetID() int {
return ct.ID
}
func (ct CommentTest) GetParentID() int {
return ct.ParentID
}
// works well, all public properties are 100% accesible
func (ct CommentTest) String() string {
return "{ID: " + strconv.Itoa(ct.ID) + ", ParentID: " + strconv.Itoa(ct.ParentID) + ", Title: " + ct.Title + "}"
}
/*
There are test comments with this structure:
1 ->
2 ->
4
3 ->
5
*/
func testData() (Comment, []Comment) {
var plain []Comment
root := &CommentTest{ID: 1, ParentID: 3, Title: "Test 1"} // ParentID 3 -> Check for infinite recursion
plain = append(plain, root)
plain = append(plain, &CommentTest{ID: 2, ParentID: 1, Title: "Test 2"})
plain = append(plain, &CommentTest{ID: 3, ParentID: 1, Title: "Test 3"})
plain = append(plain, &CommentTest{ID: 4, ParentID: 2, Title: "Test 4"})
plain = append(plain, &CommentTest{ID: 5, ParentID: 3, Title: "Test 5"})
return root, plain
}
func main() {
root, plain := testData()
fmt.Println(root) // works well
root.Title //root.Title undefined (type Comment has no field or method Title)
}

答案1

得分: 2

变量root的类型是Comment,它是一个接口,因此它是一组方法。它没有任何成员变量。

你可以做以下几件事情:

  • 如你所提到的,使用类型断言。
  • CommentTest中添加一个GetTitle()方法,并使用一个单独的接口:
type titler interface { GetTitle() string }
if t, ok := root.(titler); ok {
    t.GetTitle()
}
英文:

The variable root is of type Comment, which is an interface, thus, it is a set of methods. It does not have any member variables.

There are several things you can do:

  • Use type assertion, as you mentioned.
  • Add a GetTitle() method to CommentTest, and use a separate interface:
type titler interface { GetTitle() string }
if t, ok:=root.(titler); ok {
t.GetTitle()
}

答案2

得分: 1

接口只提供对方法的访问,而不提供对字段的访问(它们对于隐藏在其后面的字段布局或是否为结构体都是不可知的)。您可以向接口添加一个GetTitle()方法,并使用它。

英文:

Interfaces only provide access to methods, not fields (they're agnostic to the field layout of whatever hides behind them, or whether it's even a struct). You can add a GetTitle() method to the interface, and use that.

huangapple
  • 本文由 发表于 2021年7月7日 00:44:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/68274434.html
匿名

发表评论

匿名网友

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

确定