Note: it's a PHP Project
I have a situation where i use 2 API providers for my project. They are like similar with what info they (API) provides. I must set this right way since maybe tomorrow there will be some more APIs added. So my project will need some methods. Basic, here is what i have so far:
abstract class A {}// first api class, mostly contains API configs and call
abstract class B {}// second api class, also mostly contains API configs and call
//than first API has a sub classes of something like cars and trucks
class Car extends A implements ApiMethodsInterface {} // for the cars
class Truck extends A implements ApiMethodsInterface {} // for the trucks
//now second API has a sub classes for cars , trucks and spaceships
class Car extends B implements ApiMethodsInterface {} // for the cars
class Truck extends B implements ApiMethodsInterface {} // the trucks
class SpaceShip extends B implements ApiMethodsInterface {} // for the space ships
//they all have more or less similar methods
// so i used an Interface that all above classes
interface ApiMethodsInterface
//methods are
public function getModels()
public function getYears()
public function getPrice()
since every sub class implements this interface , i code by interface
Now, i have a situation, where SpaceShips has more methods to add, like getEquipment() and some more info, methods that other classes are not implementing. Trucks also has more methods that others do not implements , like, hasTrailer(), trailerLength() etc...
My question is , what to do now, should i use Interface segregation, and add Interfaces to classes that implements those methods, and later check if object instantiated is having this method than run, else some exception, or to add missing models into the abstract classes A and B, and override methods into the classes that use those methods, or maybe there is even more good way of solving this. Quite new into Design Patterns btw...
Maybe i am overengineering but i really want to do this in a good way.
Thanks
CodePudding user response:
It would likely help you to draw a diagram but we can talk through it.
It's completely normal for different implementors of an interface to have methods the others do not. The interface specifies the methods that all implementors share in common and when you code to the interface you just call those methods, not others the class may also declare. Any implementation of the iterface can be used interchangeably with any other implementation. The client doesn't care what other methods the implementor has, it is only interested in using the interface methods.
But code that is not acting as a client of the interface may view the implementation in a completely different way. Some other piece of code may construct a new SpaceShip and call getSpaceEquipment(). That's also normal. If you construct a new Truck then you can't call getSpaceEquipment() because that class does not have that method.
It would be a mistake to add methods like getSpaceEquipment() to the interface that Truck and SpaceShip both implement, say Vehicle. getSpaceEquipment() only makes sense for a SpaceShip not for all Vehicles.
You could create an extension of Vehicle called SpaceVehicle and declare the getSpaceEquipment() method in it. Then SpaceShip could implement SpaceVehicle (which makes it also a Vehicle by inheritance). But you would only do that if you were going to have several implementors of SpaceVehicle and you needed to write code that works with SpaceVehicle instances but does not care whether the SpaceVehicle is a SpaceShip or a Satelite or whatever.