An alternative to multiple inheritance when creating an abstraction layer?
- by sebf
In my project I am creating an abstraction layer for some APIs. The purpose of the layer is to make multi-platform easier, and also to simplify the APIs to the feature set that I need while also providing some functionality, the implementation of which will be unique to each platform.
At the moment, I have implemented it by defining and abstract class, which has methods which creates objects that implement interfaces.
The abstract class and these interfaces define the capabilities of my abstraction layer.
The implementation of these in my layer should of course be arbitrary from the POV view of my application, but I have done it, for my first API, by creating chains of subclasses which add more specific functionality as the features of the APIs they expose become less generic.
An example would probably demonstrate this better:
//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);
}
}
As can be seen, I am essentially trying to have two inheritance chains on the same object, but of course I can't do this so I simulate the second version with interfaces.
The thing is though, I don't like using interfaces for this; it seems wrong, in my mind an interface defines a contract, any class that implements that interface should be able to be used where that interface is used but here that is clearly not the case because the interfaces are being used to allow an object from the layer to masquerade as something else, without the application needing to have access to its definition.
What technique would allow me to define a comprehensive, intuitive collection of objects for an abstraction layer, while their implementation remains independent?
(Language is C#)