Golang继承 – 无法将类型func(d Dog)用作类型func(animal Animal)。

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

Golang inheritance - Cannot use (type func(d Dog)) as the type func(animal Animal)

问题

我正在尝试编写一个名为callGetName的方法,该方法可以将getCatNamegetDogName方法作为参数传递,但我的IDE告诉我:

> 无法将类型为func(d Dog)getDogName用作类型为func(animal Animal)的参数

package main

type Animal struct {
	Name string
}
type Cat struct {
	Animal
}
type Dog struct {
	Animal
}

func getCatById(c Cat) {}
func validateDogNames(d Dog) {}

func invokeFunc(f func(animal Animal)) {}

func main() {
	invokeFunc(getCatById)
	invokeFunc(validateDogNames)
}

我试图分析原因,也许是因为Go语言支持多重继承?

请告诉我是否我做了一些愚蠢的事情,或者是否有更好的方法来实现这个目标?

========

关于我为什么要尝试这样做的更多信息:在go-kit框架中,我必须为每个单独的服务方法编写makeEndpoint函数。我使用反射来采用通用的makeEndpoints,如下所示:

func NewProductEndpoints() ProductEndpoints {
	ps := service.NewProductService()
	return ProductEndpoints{
		GetProductById: makeEndpoint(ps, util.GetFunctionName(ps.GetProductById)),
		CreateProduct: makeEndpoint(ps, util.GetFunctionName(ps.CreateProduct)),
	}
}

func makeEndpoint(s service.ProductService, funcName string) kitEndpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (response interface{}, err error) {
		req := request.(domain.ProductDTO)
		currFunc := reflect.ValueOf(s).MethodByName(funcName)
		args := []reflect.Value{reflect.ValueOf(req)}
		res := currFunc.Call(args)[0]
		return res, nil
	}
}

想知道是否有更好的方法来实现这个目标。提前感谢。

英文:

I was tring to write a method callGetName which can take both getCatName and getDogName method as its parameter while my IDE tells me:

> Cannot use 'getDogName' (type func(d Dog)) as the type func(animal Animal)

package main

type Animal struct {
	Name string
}
type Cat struct {
	Animal
}
type Dog struct {
	Animal
}

func getCatById(c Cat) {}
func validateDogNames(d Dog) {}

func invokeFunc(f func(animal Animal)) {}

func main() {
	invokeFunc(getCatById)
	invokeFunc(validateDogNames)
}

I tried to analyze the reason, maybe it's because golang supports multiple inheritance?

Please let me know if I was doing something stupid or is there any better way to achieve this?

========

A little more about why I'm trying this: in go-kit framework, I have to write makeEndpoint functions for every single service method defined. And I used reflect to adopt a generic makeEndpoints like below:

func NewProductEndpoints() ProductEndpoints {
	ps := service.NewProductService()
	return ProductEndpoints{
		GetProductById: makeEndpoint(ps, util.GetFunctionName(ps.GetProductById)),
		CreateProduct: makeEndpoint(ps, util.GetFunctionName(ps.CreateProduct)),
	}
}

func makeEndpoint(s service.ProductService, funcName string) kitEndpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (response interface{}, err error) {
		req := request.(domain.ProductDTO)
		currFunc := reflect.ValueOf(s).MethodByName(funcName)
		args := []reflect.Value{reflect.ValueOf(req)}
		res := currFunc.Call(args)[0]
		return res, nil
	}
}

wondering if there's a better way to achieve. Thanks in advance.

答案1

得分: 2

所以你在以一种相当面向对象的方式思考,Go语言没有继承(澄清一下,它有结构体嵌入,这就是你在第一个示例中所做的)。我们倾向于使用组合来解决问题。

你可以通过以下方式来解决你的问题:

package main

import (
	"fmt"
)

type Namer interface {
	Name() string
}

type Cat struct {
	name string
}

func (c Cat) Name() string {
	return c.name
}

type Dog struct {
	name string
}

func (d Dog) Name() string {
	return d.name
}

func PetName(n Namer) {
	fmt.Println(n.Name())
}

func main() {
	PetName(Dog{name: "Fido"})
	PetName(Cat{name: "Mittens"})
}

名称可以改进,但它应该作为一个基本示例,展示了一种可能的方法。

编辑:根据下面的评论留言的示例

package main

import (
	"fmt"
)

type Invoker interface {
	Invoke()
}

type Dog struct{}

func (Dog) Bark() {
	fmt.Println("Woof")
}
func (d Dog) Invoke() {
	d.Bark()
}

type Cat struct{}

func (Cat) Meow() {
	fmt.Println("Meow")
}
func (c Cat) Invoke() {
	c.Meow()
}

func CallFunc(i Invoker) {
	i.Invoke()
}

func main() {
	CallFunc(Cat{})
	CallFunc(Dog{})
}

希望对你有帮助!

英文:

So you're thinking in a fairly OOP fashion, Go does not have inheritance (to clarify it has struct embedding which is what you are doing in your first example). We tend to favour composition to solve problems.

One way you could look at solving your problem is like the below.

package main

import (
	"fmt"
)

type Namer interface {
	Name() string
}

type Cat struct {
	name string
}

func (c Cat) Name() string {
	return c.name
}

type Dog struct {
	name string
}

func (d Dog) Name() string {
	return d.name
}

func PetName(n Namer) {
	fmt.Println(n.Name())
}

func main() {
	PetName(Dog{name: "Fido"})
	PetName(Cat{name: "Mittens"})
}

Names can be improved, but it should act as a basic example of an approach that could be taken.

Edit: Example based on comment left below

package main

import (
	"fmt"
)

type Invoker interface {
	Invoke()
}

type Dog struct{}

func (Dog) Bark() {
	fmt.Println("Woof")
}
func (d Dog) Invoke() {
	d.Bark()
}

type Cat struct{}

func (Cat) Meow() {
	fmt.Println("Meow")
}
func (c Cat) Invoke() {
	c.Meow()
}

func CallFunc(i Invoker) {
	i.Invoke()
}

func main() {
	CallFunc(Cat{})
	CallFunc(Dog{})
}

huangapple
  • 本文由 发表于 2021年10月13日 17:26:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/69552923.html
匿名

发表评论

匿名网友

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

确定