Introduction​

Interfaces 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:
  1. 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.
  2. 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.
  3. 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
  4. 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.
Xbase++ supports multiple inheritance which is a powerful generic concept. In fact languages such as Java or C# implement interfaces via a very specialized kind of multiple inheritance. In Xbase++ we simple create an abstract class that acts like an interface. This is done by defining a class with only deferred methods using the deferred keyword.

Example​

Here's an example of how an interface-like structure can be created:
Xbase++:
CLASS IMyInterface
   EXPORTED:
   DEFERRED METHOD doSomething()
   DEFERRED METHOD doAnotherThing()
ENDCLASS

A class that wants to implement this interface would do so like this:
Xbase++:
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++:
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

Some notes:
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 interface​

Now, 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.

Xbase++:
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.

Summary

Xbase++ comes with all the tools required to adapt/ use the concept of interfaces. Allowing an Xbase++ code base to be more robust and better decoupled. If used consequently, design and usage of interfaces can dramatically reduce your maintenance costs of your software.