Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

go

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?

like image 460
Darrrrrren Avatar asked Oct 03 '14 14:10

Darrrrrren


People also ask

How would you implement an interface in another package?

Create a file vehicle.go inside the vehicle folder. The file inside the vehicle folder should start with the line package vehicle as it belongs to the vehicle package. We added the method Structure() and Speed() to the receiver type Car. Now Car is said to implement the interface Vehicle.

Can an interface have package private methods?

An interface can have private methods since Java 9 version. These methods are visible only inside the class/interface, so it's recommended to use private methods for confidential code.

Can interface be package private in Java?

From Java 9, private methods can be added to interfaces in Java.


1 Answers

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()
}
like image 76
Simon Fox Avatar answered Oct 11 '22 22:10

Simon Fox