Go语言中的多态性

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

Polymorphism in Go lang

问题

我正在学习Go语言,我想知道是否有一种方法可以做到这样:

type Foo struct {
   ...
}

type Bar struct {
   Foo
   ...
}

func getFoo() Foo {
   return Bar{...}
}

在面向对象的语言中,这样的代码应该没有问题,但在Go语言中,它会抛出一个错误,说getFoo()必须返回一个Foo类的实例。

在Go语言中是否有一种类似于我描述的多态的方法?

英文:

I am learning go lang and i was wondering if there is a way to do something like this:

type Foo struct {
   ...
}

type Bar struct {
   Foo
   ...
}

func getFoo() Foo {
   return Bar{...}
}

In an object oriented language, such code should work without problems, but in go it throws me an error, saying that getFoo() must return an instance of class Foo.

Is there a way to do polymorphism similar to what i've described in Go?

答案1

得分: 21

Go不是一种典型的面向对象语言。此外,每种语言都有自己的做事方式。你可以使用接口和组合来实现你想要的效果,如下所示:

package main

import "fmt"

type Foo interface {
   printFoo()
}

type FooImpl struct {
   
}

type Bar struct {
   FooImpl
}

type Bar2 struct {
   FooImpl
}

func (f FooImpl)printFoo(){
	fmt.Println("Print Foo Impl")
}

func getFoo() Foo {
   return Bar{}
}

func main() {
	fmt.Println("Hello, playground")
	b := getFoo()
	b.printFoo()
}

你可以在这里查看代码:http://play.golang.org/p/iR8QkD3DnP

英文:

Go is not a typical OO language. Also each language has it own way of doing things. You can use interface and composition to achieve what you desire to, as shown below:

package main

import "fmt"

type Foo interface {
   printFoo()
}

type FooImpl struct {
   
}

type Bar struct {
   FooImpl
}

type Bar2 struct {
   FooImpl
}

func (f FooImpl)printFoo(){
	fmt.Println("Print Foo Impl")
}

func getFoo() Foo {
   return Bar{}
}

func main() {
	fmt.Println("Hello, playground")
	b := getFoo()
	b.printFoo()
}

http://play.golang.org/p/iR8QkD3DnP

答案2

得分: 6

在Go语言中,通过实现接口来实现多态性。

type Being interface {
    somemethod()
}

type Foo struct {}

type Bar struct {
    Foo
}

type Baz struct {
    Foo
}

// `Bar`和`Baz`实现了`Being`接口
func (b *Bar) somemethod() {}
func (b *Baz) somemethod() {}

func getAnyFoo(b *Being) Foo {
    return b.Foo
}

因此,任何东西都可以实现一个空接口。

type Foo struct {}

type Bar struct {
    Foo
}

// 获取任何东西并提取其`Foo`,如果任何东西是一个Bar
func getAnyFoo(i interface{}) Foo {
    // 通常需要使用类型切换来检查类型
    mybar := i.(Bar)
    return mybar.Foo
}
英文:

In Go, polymorphism is achieved by implementing interfaces.

type Being interface {
        somemethod()
}

type Foo struct {}

type Bar struct {
        Foo
}

type Baz struct {
        Foo
}

// `Bar` and `Baz` implement `Being`
func (b *Bar) somemethod() {}
func (b *Baz) somemethod() {}

func getAnyFoo(b *Being) Foo {
   return b.Foo
}

Therefore, anything implements an empty interface.

type Foo struct {}

type Bar struct {
        Foo
}

// Get anything and extract its `Foo` if anything is a Bar
func getAnyFoo(i interface{}) Foo {
        // Normally this would need a type switch to check the type
        mybar := i.(Bar)
        return mybar.Foo
}

答案3

得分: 0

如果你知道要使用的类型,你可以将它们放入一个数组列表中,以实现一种多态实例化:

package main
import (
  "fmt"
  "encoding/json"
)

type Hans struct{
      Miau string
    }

type Keule struct {
  Wuff string
}

func (K Keule)ppp() {
  fmt.Printf(K.Wuff)
}

func (K Hans)ppp() {
  fmt.Printf(K.Miau)
}

func (K Keule)TypeInfo() int {
  return 0
}

func (K Hans)TypeInfo() int {
  return 1
}

type Mega interface {
  ppp()
  TypeInfo() int
}


var j_a = `{
  "Kein_Alter": "nix",
  "Miau": "lala",
  "class": 0
}`

var j_b = `{
  "Alter": "nix",
  "Wuff": "lolo",
  "Class": 1
}`

type Class struct {
  Class int
}

func (K *Class)ppp() {
  fmt.Printf("%d", K.Class)
}

func Unmarshal_K(b []byte) (Mega, error) {
  var k Keule
  err := json.Unmarshal([]byte(j_a), &k)
  return k, err
}

func Unmarshal_H(b []byte) (Mega, error) {
  var k Hans
  err := json.Unmarshal([]byte(j_a), &k)
  return k, err
}

var UList = []func(b []byte) (Mega, error) {Unmarshal_H, Unmarshal_K}

func main() {
  var mv Class
  err := json.Unmarshal([]byte(j_a), &mv)
  if err != nil {
    panic(err)
  }


  hiho, err := UList[mv.Class]([]byte(j_a))
  if err != nil {
    panic(err)
  }


  hiho.ppp()
}

希望对你有帮助!

英文:

If you know the types to use you could put them to an array list to implement a kind of polymorph instancing:

package main
import (
"fmt"
"encoding/json"
)
type  Hans struct{
Miau string
}
type  Keule struct {
Wuff string
}
func (K Keule)ppp() {
fmt.Printf(K.Wuff)
}
func (K Hans)ppp() {
fmt.Printf(K.Miau)
}
func (K Keule)TypeInfo() int {
return 0
}
func (K Hans)TypeInfo() int {
return 1
}
type Mega interface {
ppp()
TypeInfo() int
}
var j_a = `{
"Kein_Alter": "nix",
"Miau": "lala",
"class": 0
}`
var j_b = `{
"Alter": "nix",
"Wuff": "lolo",
"Class": 1
}`
type Class struct {
Class int
}
func (K *Class)ppp() {
fmt.Printf("%d", K.Class)
}
func Unmarshal_K(b []byte) (Mega, error) {
var k Keule
err := json.Unmarshal([]byte(j_a), &k)
return k, err
}
func Unmarshal_H(b []byte) (Mega, error) {
var k Hans
err := json.Unmarshal([]byte(j_a), &k)
return k, err
}
var UList = []func(b []byte) (Mega, error) {Unmarshal_H, Unmarshal_K}
func main() {
var mv Class
err := json.Unmarshal([]byte(j_a), &mv)
if err != nil {
panic(err)
}
hiho, err := UList[mv.Class]([]byte(j_a))
if err != nil {
panic(err)
}
hiho.ppp()
}

答案4

得分: 0

你可以按照以下方式使用它。如果你给print函数传递一个person或secretAgent对象,它会理解这是直接来自人类界面的,并执行其中的函数。

package main

import "fmt"

type person struct {
	firstName string
	lastName  string
	age       int
}

type secretAgent struct {
	person
	ltk bool
}

type human interface {
	info() string
}

func (p person) info() string {
	return fmt.Sprint("姓名:", p.firstName, " 姓氏:", p.lastName, " 年龄:", p.age)
}

func (s secretAgent) info() string {
	return fmt.Sprint("姓名:", s.firstName, " 姓氏:", s.lastName, " 年龄:", s.age, " Ltk:", s.ltk)
}

func print(h human) {
	switch h.(type) {
	case person:
		fmt.Println("person结构体:")
		fmt.Println(h.info())
	case secretAgent:
		fmt.Println("secretAgent结构体:")
		fmt.Println(h.info())
	}
}

func main() {

	p := person{
		firstName: "Khanbala",
		lastName:  "Reshidov",
		age:       22,
	}

	s := secretAgent{
		person: p,
		ltk:    true,
	}

	//info方法
	fmt.Println(p.info())
	fmt.Println(s.info())

	//多态性
	print(p)
	print(s)

	//类型
	fmt.Printf("%T\n", p)
	fmt.Printf("%T\n", s)
}
英文:

You can use it in the following way. If you give the print function one of the person or secret Agent, it will understand that it came directly from the human interface and run the function inside it.

package main

import "fmt"
type person struct {
firstName string
lastName  string
age       int
}
type secretAgent struct {
person
ltk bool
}
type human interface {
info() string
}
func (p person) info() string {
return fmt.Sprint("Name:", p.firstName, " Surname:", p.lastName, " Age:", p.age)
}
func (s secretAgent) info() string {
return fmt.Sprint("Name:", s.firstName, " Surname:", s.lastName, " Age:", s.age, " Ltk:", s.ltk)
}
func print(h human) {
switch h.(type) {
case person:
fmt.Println("person struct:")
fmt.Println(h.info())
case secretAgent:
fmt.Println("secretAgent struct:")
fmt.Println(h.info())
}
}
func main() {
p := person{
firstName: "Khanbala",
lastName:  "Reshidov",
age:       22,
}
s := secretAgent{
person: p,
ltk:    true,
}
//info Method
fmt.Println(p.info())
fmt.Println(s.info())
//polymorphism
print(p)
print(s)
//type
fmt.Printf("%T\n", p)
fmt.Printf("%T\n", s)
}

huangapple
  • 本文由 发表于 2016年1月31日 23:11:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/35115385.html
匿名

发表评论

匿名网友

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

确定