A real basic introduction to software interfaces.

So this example does not nearly cover all the aspects of software interfaces, but if you wish to know what they generally do in a nutshell, this is a good starting point.

This piece assumes the following foreknowledge:

  • Some object orientated design programming experience.
  • Ability to read C# code.

Let’s start off by having a quick glance at the definition for interfaces, found in MSDN:

An interface contains only the signatures of methodspropertiesevents or indexers. A class or struct that implements the interface must implement the members of the interface that are specified in the interface definition. In the following example, classImplementationClass must implement a method named SampleMethod that has no parameters and returns void.

[MSDN https://msdn.microsoft.com/nl-nl/library/87d83y5b.aspx]

Cryptic enough for you? Let’s just take two important points from the above to get started.

Rule 1: All members (everything listed in the interface) must always be visible/accessible. The outside world needs to be able to call them. In C#  this is enforced by the compiler. So mostly you will not have to worry too much about this, you can count on the compiler to let you know when you did it wrongly!

Rule 2: The” thing” (usually a class) that implements (this means that it undertakes to actually add some code to these members listed in the Interface) MUST have an implementation for each of the  members of the interface.

As always it makes much more sense when explained by means of an example. Let’s say we have a company called Robot Inc that produces robots . We produce robots based on the George Lucas all time classic movie Start Wars – (sort of!). The range include the following robots.

Snap 2015-07-21 at 22.42.35

So we have all these Robots and  they are jam-packed with functionality, but let’s for the moment only try and focus on the movement aspect that each one of them have. Maybe a mind-shift, but unlike in the movies these Robots are controlled by Humans and cannot function on their own!

So important to note is that all of these Robots have the ability to move, move forward in particular. However, the means of achieving this differs with each one of them. For instance R2-D2 has three struts with tracks that can move him forward, C3PO uses two legs and loads of balancing censors, the Walker uses 4 giant legs and Wall-E uses 2 tracks. Each one of these moving parts have a complex way of working together in order to achieve the same result  – getting  from point A to B.

A bit silly, but for the moment try to imagine that a user had to give individual commands to each Robot to get it to move forward, what will these look like?

R2-D2:

  1. Activate IR detection sensors.
  2. Is there enough space to move forward?
  3. Engage power source.
  4. Releasing the break if active.
  5. Re-angle tracks in the forward direction.
  6. Slowly engage all 3 track mechanisms.
  7. Slowly increment speed until it reaches the configured max speed.

Walker:

  1. Activate radar and scan parameter.
  2. Determine proximity of objects and possible distance to move forward?
  3. Engage power source.
  4. Releasing, if active, the braking mechanisms in the legs.
  5. Check all 4 legs are in ground position.
  6. While performing a balance check lift front right leg.
  7. While performing a balance check lift left rear leg.
  8. While performing a balance check extend front right leg forward.
  9. While performing a balance check extend front left rear leg forward.
  10. While performing a balance check ground front right leg.
  11. While performing a balance check ground left rear leg
  12. Repeat 6 – 11 Slowly alternating between leg pairs FR-RL | FL-RR
  13. Increment speed until it reaches the configured max speed.

I think for the above at least two things are clear 1) I am definitely no robotics expert and 2) it takes a lot of combined systems and complex actions just to get the Robots to move forward. Expecting the owner of these robots to remember each robot’s unique “move forward instructions” in order to control them, would be madness.

How will one solve this? Enter Interfaces!

Let’s create the following interface IRobot.

IRobot-Interface

And then implement it on each Robot and let the user use the interface to control the Robots.

User-Controls-Robots-via-Interface

Implement, what does that mean!?

This refers to the actions undertaken by the consumer of the interface, in our case the robots. The consumer of the interface needs to provide each member of the Interface with a body, preferably filled with some meaningful code!  Keep in mind that in our example each Robot is represented by a Class, for example Class R2_D2. When a Robot implements a class it is done by the following notation to right of the class name:

class R2_D2 : IRobot

In C# the double colon depicts the implementation of an Interface . Note: it can also refer to inheritance, but this can be ignored for now.

What does this mean to the class that implements the interface? What is expected of it?

It means that if Class R2_D2 chooses to implement the Interface IRobot , it (the class R2_D2) MUST implement all of the members of IRobot. For example:

  • All the members that exist on the interface MUST be present and have a body! (remember the definition in the beginning?!)
  • All return types MUST be honored and return the data type as specified!

Capture

These are the bare basics of what is required of the class R2_D2 when it implements the IRobot Interface! It will compile, but obviously it would be a bit silly to leave the members’ bodies empty. If the members’ bodies contains no code and gets called, obviously nothing will happen. So let’s move on.

So now each one of our Robots implements this IRobot Interface. Using the R2_D2 class, we will now go a step further and populate these members. Because we want to concentrate on the movement aspect – we will only focus on the MoveForward  function. So you will notice that all the instructions needed to make R2-D2 move forward (which we discussed earlier on) are now in the “MoveForward“ function. When the “MoveForward“ function will be called on the R2_D2 class, it will now move forward!

Snap 2015-07-28 at 22.13.36

So how do we use this?

Well, it just got a whole lot easier to control R2-D2! The person wanting to control it, now needs to know very little about how R2-D2 works – in fact, zero! All of the technical steps are unknown to him. All that you need to know is that R2-D2 implements the IRobot interface. You are (and anyone else using the class) allowed to “get” this interface, furthermore you also have the right to call ANY of the functions / members on the interface at will and R2-D2 should respond accordingly. This is the very obvious reason why this rule exists, the rule stating that the class that implements an interface  MUST implement all of the members contained in it. Seeing that anyone can get the interface and call any of the functions / members on it, it needs to be implemented in the class that implements it, otherwise things will go haywire! Hence the reason the compiler prevents this by checking that ALL functions / members of the interface were implemented by the consuming class. The C# compiler takes care of this by doing compile time checking, and prevents the project from compiling if this is not the case.

Getting the interface from a class that implemented it, is pretty easy.

There is the long way:

IRobot robot = null;

robot = new R2_D2();

And the shorter way:

IRobot robot = new R2_D2();

It really does not differ all that much from the usual newing up of an instance of a class. The only difference being, that the compiler detects that the return type expected is an interface that matches an interface that is implemented by the Class R2_D2.  So you are getting an Interface back of the type IRobot , but importantly the one from the class R2_D2!  And as seen, the interface member “MoveForward“ has been populated with very specific R2_D2 instruction. Maybe a good metaphor for this is to imagine the Interface IRobot as a remote control. The remote control has the exact button (members / functions)  that you can use / call. It just depends from which class you have retrieved this remote. The function call “MoveForward“ will always be available for you to call no matter from which class you retrieve it, the only difference being that when you call it,  the functionality of the class where you retrieved it from will execute!

This is really important, so here goes : the functionality of the class where you retrieved it from will be executed!  So the “remote” is always the same, ie the same “MoveForward button“ is found on each one. More importantly, is where you got it from. Calling the “MoveForward” function will trigger vastly different code, pending whether you retrieved it from R2_D2 or the Walker for instance!

So to illustrate this:

  1. The user retrieves the interface IRobot from R2_D2 in A.
  2. The user calls the “MoveForward“ function in B (Note that the user has no idea of what actual code will be executed when calling this, it just knows that calling this function will make the robot (R2-D2) move forward).
  3. The code that was implemented on the class for the member of the interface (in this case “MoveForward“)  will be executed  in C.  Note, the class in question is the class where the Interface was retrieved from!
  4. The function “MoveForward“ will be executed and R2-D2 will move forward in D.

Retrieve_IRobot

To take it up a notch and demonstrate the true “facelessness” of interfaces, have a look at the following. Let’s say you want to control two robots at the same time. For example, you want them both to move forward at the same time.

  • In “A” we create a List<T> called “robots”, containing Interface objects of the type IRobot.
    1. In A.1 we new up an instance of the class type R2_D2 , retrieving the interface IRobot from that class and storing it at position zero in our List “robots”.
    2. In B.1 we new up an instance of the class type Walker, retrieving the interface IRobot from that class and storing it at position one in our List “robots”.
  • In B we loop through our List<T> collection “robots” and call the “MoveForward“  function on each IRobot interface in the List.
  • When the first IRobot interface is retrieved and the “MoveForward“ function is called, it will call the implemented code on the class where it was retrieved from.
    1. C.1 the “MoveForward“ function in the R2_D2 class will be executed!
    2. C.2 the “MoveForward“ function in the Walker class will be executed!
  • The result being that both R2_D2 and Walker will move forward simultaneously !

Retrive_2_IRobots

This is one of the great strengths of Interfaces. The consumer of the interface neither knows nor cares about what goes on in the class where the interface is retrieved from (also referred to as the “Concrete Class”), it just knows:

  • That it contains certain members, and what their purposes are (for instance “MoveForward” will make the Robot move forward.
  • What the members’ expected parameters are.
  • What the members’ return values need to be.

In this way you can control / handle different classes in the exact same way, as long as they implement the same Interface. This attribute is also known as polymorphism in the object orientated design world. The root of the word (polymorphism) sums it up pretty well -> from the Greek πολύς, polys, “many, much” and μορφή, morphē, “form, shape“)

Handling many forms or types in the same way – provided that there is a common interface!