Implémentation d'interfaces avec des méthodes non exportées à partir d'autres packages
Dans Go, les interfaces servent de contrats qui définissent un ensemble de méthodes qui doivent être implémentées par tout type qui y adhère. Généralement, les méthodes d'une interface sont exportées pour permettre l'accès depuis d'autres packages. Cependant, il peut y avoir des scénarios dans lesquels vous devez masquer des implémentations spécifiques du programme consommateur.
Considérez l'exemple suivant, dans lequel nous définissons une interface pour l'accès au système comptable :
package accounting import "errors" type IAdapter interface { GetInvoice() error }
Pour masquer implémentations spécifiques, nous rendons les méthodes d'interface non exportées et introduisons des fonctions wrapper dans le package de base qui invoquent l'implémentation appropriée via un adaptateur :
var adapter IAdapter func SetAdapter(a IAdapter) { adapter = a } func GetInvoice() error { if (adapter == nil) { return errors.New("No adapter set!") } return adapter.GetInvoice() }
Pendant que cela L'approche semble prometteuse, elle rencontre un problème en essayant d'implémenter l'interface dans un autre package. Le compilateur se plaint de ne pas pouvoir voir la méthode GetInvoice non exportée.
Ce problème vient du fonctionnement des interfaces dans Go. Une interface est constituée uniquement des signatures de méthodes, sans aucune connaissance de leur implémentation. Lorsqu'un type implémente une interface, il doit exposer toutes les méthodes avec les mêmes signatures que l'interface.
Pour surmonter cette limitation, nous pouvons utiliser des champs de structure anonymes :
type Adapter struct { accounting.IAdapter }
Cela permet nous d'implémenter l'interface dans un autre package en l'intégrant de manière anonyme, mais nous ne pouvons pas fournir d'implémentations personnalisées pour les méthodes non exportées.
Une solution plus idiomatique serait d'exposer un adaptateur non exporté et fournit une fonction d'enregistrement dans le package de base :
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() }
Cette approche garantit que l'adaptateur reste masqué tout en permettant l'enregistrement d'une implémentation appropriée.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!