2014-09-02 58 views
1

我想创建一些通用函数来处理大量不同的对象类型,其中一些类型嵌入了我创建的方便的子类型调用BaseObject。在GoLang中访问嵌入的方法

我似乎无法弄清楚如何测试'Value interface {}'是否包含BaseObject,或者如何调用其中一个方法,例如的ToString()...这应该返回[TestObject中]不是[BaseObject]

package Test 

import(
    "fmt" 
    "reflect" 
) 

func main() { 
    Value:=TestObject{} 
    TestFunction(Value) 
} 

//Generic function 
func TestFunction(Value interface{}){ 

    // Does value contain BaseObject? reflect.TypeOf(Value).Containes...Implements?? 
    //Convert to BaseObject? BO:=Value.(BaseObject) 
    // If it does, call BO.ToString() 
    //fmt.println(BO.ToString()) 
} 

//Base Object 
type BaseObject struct { 
} 
func (this *HCObject) ToString() string { 
    return "[BaseObject]" 
} 

//Test Object 
type TestObject struct{ 
    BaseObject 
} 
func (this *TestObject) ToString() string { 
    return "[TestObject]" 
} 
+0

另请参阅http://stackoverflow.com/a/23148998/6309关于'interface {}的更多信息 – VonC 2014-09-02 14:26:16

+2

如果您尝试在Go中执行“经典”OOP,您会感到失望。你确定你找不到类似Go的解决方案吗? – Volker 2014-09-02 14:29:12

+3

在Go中,您将会更好*而不是*尝试编写类风格的面向对象代码。 Go没有类,子类,继承等等。 – JimB 2014-09-02 14:29:19

回答

3

首先,几个百分点的:

  • 这是一个很好的做法,让链接在play.golang.org工作代码示例。
  • 总是找到你的代码。
  • ToString应该是String。请参阅fmt.Stringer界面。
  • 正如其他人所指出的,尝试在Go中编写C++的Java将在后面记录痛苦日志。

这样说,this是一个可运行的代码示例,可以实现许多buts所需的功能。

func TestFunction(v interface{}) { 
    fmt.Println(reflect.ValueOf(v).FieldByName("BaseObject").MethodByName("String").Call(nil)[0].String()) 
} 

该代码使用reflect包(这是一件好事,只有当你真正需要是你应该做的)。我建议你玩这个例子,并深入探索reflect,看看它是否值得继续与Go一起走。

+0

这看起来像解决方案。我仍然试图让它在我自己的代码中工作,但是你在play.golang.org上的演示作品。谢谢。 – 2014-09-02 15:38:29

+0

@GordonTruslove:在这种情况下不需要使用反射(如果可能,您应该避免使用) - 您可以使用接口[EXAMPLE](http://play.golang.org/p/VyoUW18NGU)完全完成此操作。请注意,您必须确保您传递一个指针以匹配方法集。 – JimB 2014-09-02 16:13:31

+0

这个例子是最好的解决方案。我将尝试实现这一点。这只是意味着额外的工作来实现所有额外的接口方法。谢谢。 – 2014-09-02 20:30:35

2

你不是 “嵌入” 到interface{}。接口本身有一个方法集,并且包含一些值和它的类型信息。

使用Type Assertion从接口提取值。

你的测试功能可以包含类似:

bo, ok := value.(BaseObject) 
if ok { 
    fmt.Println(bo) 
} 

如果要检查多个类型,你用型开关。在你的情况下,TestObject和BaseObject是完全不同的类型; TestObject不是BaseObject。

switch bo := value.(type) { 
case TestObject: 
    fmt.Println("TestObject", bo) 
case BaseObject: 
    fmt.Println("BaseObject", bo) 
} 

如果您需要这两种类型之间的区别,具有嵌入式类型的方法的一个超集嵌入类型,定义符合您需要的方法是接口。

type Base interface { 
    MethodA() 
} 

type Sub interface { 
    MethodA() 
    MethodB() 
} 

在这种情况下Sub是一个Base,在任何满足Sub接口,也满足了Base接口。

+0

我以前都在尝试这两种方法,但都无效。只有值(TestObject)和case TestObject:有效。 – 2014-09-02 14:55:15

+0

尝试创建可运行的示例。来自类型断言的错误说明了你的问题'恐慌:接口转换:接口是main.TestObject,而不是main.BaseObject'。再次,*在Go *中没有继承。没有类型 - >嵌入式是一种关系。嵌入只是一种方便的委托形式,您可以使用接口来实现多态。 – JimB 2014-09-02 15:09:33