在另一个包中实现具有未导出方法的接口是否可能?

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

Is it possible to implement an interface with unexported methods in another package?

问题

我已经为会计系统访问编写了一个接口。我希望隐藏接口的特定实现,因为我只会有一个“活动”的会计系统。所以我计划将接口的方法设为未导出(隐藏),然后在基础包中编写导出函数,这些函数调用本地适配器中的相同函数。

package accounting

import "errors"

type IAdapter interface {
    getInvoice() error
}

var adapter IAdapter

func SetAdapter(a IAdapter) {
    adapter = a
}

func GetInvoice() error {
    if adapter == nil {
        return errors.New("No adapter set!")
    }
    return adapter.getInvoice()
}
package accountingsystem

type Adapter struct{}

func (a Adapter) getInvoice() error { return nil }
package main

import (
    "accounting"
    "accountingsystem"
)

func main() {
    adapter := accountingsystem.Adapter{}
    accounting.SetAdapter(adapter)
}

问题在于编译器抱怨无法看到accountingsystem.AdaptergetInvoice()的实现:

./main.go:2: cannot use adapter (type accountingsystem.Adapter) as type accounting.IAdapter in argument to accounting.SetAdapter:
accountingsystem.Adapter does not implement accounting.IAdapter (missing accounting.getInvoice method)
    have accountingsystem.getInvoice() error
    want accounting.getInvoice() error

有没有办法在另一个包中实现具有未导出方法的接口?还是我对这个问题的思考方式不符合惯例?

英文:

I have written an interface for accounting system access. I would like to hide specific implementations of the interface from my program as I will only ever have one "active" accounting system. So I planned on making the methods of the interface unexported (hidden), and then having exported functions native to the base package that call a the same function from a local adapter.

package accounting

import "errors"

type IAdapter interface {
    getInvoice() error
}

var adapter IAdapter

func SetAdapter(a IAdapter) {
    adapter = a
}

func GetInvoice() error {
    if (adapter == nil) {
        return errors.New("No adapter set!")
    }
    return adapter.getInvoice()
}


__________________________________________________

package accountingsystem

type Adapter struct {}

func (a Adapter) getInvoice() error {return nil}


__________________________________________________


package main

import (
    "accounting"
    "accountingsystem"
)

function main() {
    adapter := accountingsystem.Adapter{}
    accounting.SetAdapter(adapter)
}

The problem with this is that the compiler complains, due to not being able to see the implementation of getInvoice() by accountingsystem.Adapter:

./main.go:2: cannot use adapter (type accountingsystem.Adapter) as type accounting.IAdapter in argument to accounting.SetAdapter:
accountingsystem.Adapter does not implement accounting.IAdapter (missing accounting.getInvoice method)
    have accountingsystem.getInvoice() error
    want accounting.getInvoice() error

Is there any way of being able to implement an interface with unexported methods in another package? Or am I thinking about this problem in a non-idiomatic way?

答案1

得分: 16

你可以使用匿名结构字段来实现具有未导出方法的接口,但是你不能提供自己的未导出方法的实现。例如,Adapter的这个版本满足accounting.IAdapter接口。

type Adapter struct {
    accounting.IAdapter
}

我无法通过Adapter来提供自己的IAdapter.getInvoice()方法的实现。

这个技巧对你没有帮助。

如果你不希望其他包直接使用accountingsystem.Adapter,那么将该类型设为未导出,并添加一个函数来将适配器注册到accounting包中。

package accounting

type IAdapter interface {
    GetInvoice() error
}

---

package accountingsystem

type adapter struct {}

func (a adapter) GetInvoice() error {return nil}  

func SetupAdapter() {
    accounting.SetAdapter(adapter{})
}

---

package main

func main() {
    accountingsystem.SetupAdapter()
}
英文:

You can implement an interface with unexported methods using anonymous struct fields, but you cannot provide your own implementation of the unexported methods. For example, this version of Adapter satisfies the accounting.IAdapter interface.

type Adapter struct {
    accounting.IAdapter
}

There's nothing that I can do with Adapter to provide my own implementation of the IAdapter.getInvoice() method.

This trick is not going to help you.

If you don't want other packages to use accountingsystem.Adapter directly, then make the type unexported and add a function for registering the adapter with the accounting package.

package accounting

type IAdapter interface {
    GetInvoice() error
}

---

package accountingsystem

type adapter struct {}

func (a adapter) GetInvoice() error {return nil}  

func SetupAdapter() {
    accounting.SetAdapter(adapter{})
}

---

package main

func main() {
    accountingsystem.SetupAdapter()
}

huangapple
  • 本文由 发表于 2014年10月3日 22:49:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/26181271.html
匿名

发表评论

匿名网友

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

确定