IntroductionInterfaces in Object-Oriented Programming (OOP) play a critical role in designing robust software. In the following we will try to explain the benefits of using interfaces and how to implement them in Xbase++. Generally, benefits of using interface are:
- Abstraction: Interfaces provide a way to define what a class should do, but not how it should do it. This allows for a higher level of abstraction in your code.
- Loose Coupling: Since the implementation details are hidden, classes can be more loosely coupled. This makes it easier to swap out implementations without affecting other parts of the system. In practice, users of classes are only interfacing with a class using interfaces. Nothing else is generally exported.
- Polymorphism: Interfaces allow for polymorphism, which means that objects of different types can be treated as objects of a super type. This allows for more flexible and extensible code. The trick here is that a Interface can be supported by different classes which are not inherited from each other or the same base class except the interface. This is important
- Enforcing Consistency: Interfaces enforce a certain structure. Any class implementing an interface must provide an implementation for all the methods defined in the interface. Nothing can be left over.
ExampleHere's an example of how an interface-like structure can be created:
CLASS IMyInterface EXPORTED: DEFERRED METHOD doSomething() DEFERRED METHOD doAnotherThing() ENDCLASS
A class that wants to implement this interface would do so like this:
CLASS MyClass FROM IMyInterface EXPORTED: METHOD doSomething() METHOD doAnotherThing() ENDCLASS METHOD MyClass:doSomething() // Implement the method here RETURN METHOD MyClass:doAnotherThing() // Implement the method here RETURN cResult
In case a class needs to implement multiple interfaces, you can use the multiple inheritance feature in Xbase++:
CLASS MyClass FROM IMyInterface, IAnotherInterface EXPORTED: METHOD doSomething() METHOD doAnotherThing() METHOD doThirdThing() ENDCLASS METHOD MyClass:doSomething() // Implement the method here RETURN METHOD MyClass:doAnotherThing() // Implement the method here RETURN cResult METHOD MyClass:doThirdThing() // Implement the method here RETURN
Always put the interfaces first in list of classes from which you derive.
The great thing with the interface is that it requires you to implement all of the methods.
Keep in mind multiple inheritance of full featured classes is in most cases a sign of a bad design in terms of your class hierarchie.
Testing for an interfaceNow, to test whether an object is an instance supporting a certain interface, we can use the :IsDerivedFrom() method. This method checks if an object's class is derived from a specified class - in our case is derived from a interface. Since interfaces are abstract the derived class needed to implement them hence the class does support that interface.
LOCAL oInstance oInstance := MyClass():new() IF oInstance:isDerivedFrom("IMyInterface") ? "The object implements IMyInterface" ELSE ? "The object does not implement IMyInterface" ENDIF IF oInstance:isDerivedFrom("IAnotherInterface") ? "The object implements IAnotherInterface" ELSE ? "The object does not implement IAnotherInterface" ENDIF
In this code, oInstance is an instance of MyClass. The :IsDerivedFrom() method is used to check whether oInstance is derived from IMyInterface and IAnotherInterface. The output will indicate which interfaces oInstance implements.