Nel mio progetto sto creando un livello di astrazione per alcune API. Lo scopo del livello è rendere la multi-piattaforma più semplice e anche semplificare le API al set di funzionalità di cui ho bisogno, fornendo al contempo alcune funzionalità, la cui implementazione sarà unica per ciascuna piattaforma.
Al momento, l'ho implementato definendo e astrattamente la classe, che ha metodi che creano oggetti che implementano interfacce. La classe astratta e queste interfacce definiscono le funzionalità del mio livello di astrazione.
L'implementazione di questi nel mio layer dovrebbe ovviamente essere arbitraria dalla vista POV della mia applicazione, ma l'ho fatto, per la mia prima API, creando catene di sottoclassi che aggiungono funzionalità più specifiche come le funzionalità delle API espongono diventano meno generici.
Un esempio probabilmente lo dimostrerebbe meglio:
//The interface as seen by the application
interface IGenericResource
{
byte[] GetSomeData();
}
interface ISpecificResourceOne : IGenericResource
{
int SomePropertyOfResourceOne {get;}
}
interface ISpecificResourceTwo : IGenericResource
{
string SomePropertyOfResourceTwo {get;}
}
public abstract class MyLayer
{
ISpecificResourceOne CreateResourceOne();
ISpecificResourceTwo CreateResourceTwo();
void UseResourceOne(ISpecificResourceOne one);
void UseResourceTwo(ISpecificResourceTwo two);
}
//The layer as created in my library
public class LowLevelResource : IGenericResource
{
byte[] GetSomeData()
{}
}
public class ResourceOne : LowLevelResource, ISpecificResourceOne
{
int SomePropertyOfResourceOne {get{}}
}
public class ResourceTwo : ResourceOne, ISpecificResourceTwo
{
string SomePropertyOfResourceTwo {get {}}
}
public partial class Implementation : MyLayer
{
override UseResourceOne(ISpecificResourceOne one)
{
DoStuff((ResourceOne)one);
}
}
Come si può vedere, sto essenzialmente cercando di avere due catene di ereditarietà sullo stesso oggetto, ma ovviamente non posso farlo, quindi simulo la seconda versione con le interfacce.
La cosa è, però, non mi piace usare le interfacce per questo; mi sembra sbagliato, nella mia mente un'interfaccia definisce un contratto, qualsiasi classe che implementa quell'interfaccia dovrebbe essere in grado di essere usata dove viene utilizzata quell'interfaccia, ma qui chiaramente non è il caso perché le interfacce vengono utilizzate per consentire ad un oggetto di layer to masquerade come qualcos'altro, senza che l'applicazione debba avere accesso alla sua definizione.
Quale tecnica mi permetterebbe di definire una collezione completa e intuitiva di oggetti per un livello di astrazione, mentre la loro implementazione rimane indipendente?
(La lingua è C #)