I have a custom class that extends Pimple\Container. The idea was to wrap the, to my eyes, ugly methods for accessing defined services (see below):
offsetGet($key) -> get($key)
offsetSet($key, $val) -> set($key, $val)
offsetExists($key) -> has($key)
This idea worked fine for what i wanted to be able to do. i then went on to create an Application class that I chose INHERITANCE over AGGREGATION not for any particular reason than seeming to be logic.
The issue now is when I have a ServiceProvider that accepts an application instance instead of the Pimple\Container since I created my very own ServiceProviderInterface that defines this contract.
i realize now that assuming that Application was and still is a type of Container and have it use a different type of contract from the parent class wasn't a great idea. However, conceptually in my mind an application instance is some kind of a container because in it I have some key => value pair data stored.
I was thinking that Interface Segration principle would save my day but I am not sure.
Could I have violated the Liskorv Substitution Principle here with my assumption with regards to the Application extends Pimple\Container relationship?
Is there any way I can use my own Interface to register my service providers with stumbling on the error that whatever service I pass doesn't conform to the pimple\ServiceProvider contract?
In simply terms is it possible to extend Pimple's container and ignore the library's service provider and use your which defines the same contract but with different parameter?
First of all,
The ugly methods are from the
ArrayAcessinterface, which allows you to access properties in an array-like form:This is just wrong. You should always choose Aggregation over Inheritance when it is possible.
Inheritance is a static tightly-coupled relationship and it is limited to only one in PHP. You can't change inheritance during runtime.
Composition, in the other hand, is a dynamic and could be losely coupled if implemented respecting the SOLID principles. You can perfectly switch relationships during runtime when using composition.
This makes no sense! Why would you Service Provider depend on your application? Shouldn't it be the other way around? The provider is a self-contained module. Your application has several dependencies.
About your questions,
The best way of knowing if you violated the LSP is to ask yourself:
Can I substituite a
Containerobject for anApplicationobject without any loss in functionality?Nop. Interfaces are contracts and contracts should be honored.