Skip Navigation Links

Interface programming

Creating and using an interface is probably one of the most misused practices of modern programming. To fully understand them is essential today because they are used extensively by providers of developer tools and APIs.

The original intent of an interface was as the definition of a “Remote Procedure Call” and the people that invented them were concerned with how they could consistently invoke an action on a distant computer. They needed something that mimicked the syntax of a method call such as those you saw in simple classes but with the definition of how parameters might be passed and what return value should be expected.

It is important to remember that not all computers work in the same way and, for example; a number passed from one machine to another might be totally mixed up if the standards for transmission were not strictly defined.  A sixteen bit integer might be represented on machine A with the high-order bits being passed first, called “big endian.” Conversely, machine B might store it’s numbers with the low-order bits first, in other words, “little-endian”. The number F3A5 or 62373 would be seen as A5F3 or 42483 when it got to the other machine.

An interface specifies all these parameters and more such that we can be guaranteed that the procedure call will be accepted and executed no matter what the system at the other end thinks is the right way to do things. In other words, the interface enables us to ignore the details of the implementation.

In its purest form, an interface is a declaration of intent for how a “black box” mechanism should work. Take a simple radio for example. It would have three controls:

A switch to turn it on and off.

A rotary control to change the volume of the sound

A second rotary control to select the station to which you might wish to listen.

Description: A radio of the old days

The stuff that goes on inside the radio, reception and tuning of the signal, amplification and final output to the speaker is something that, as the user of the equipment, you have no interest in and no need to know. The radio is just a box that does something in a well-known way and is functionally identical to any one of a thousand other radio designs that exist. All the other radios will function in a similar manner and their controls will all be grossly similar to the ones on all the others too.

The way that the simple radio controls work is in fact a sort of contract. We know that if our radio breaks down, catches fire or just gets outmoded, we can replace it with another one and we don’t have to do any head-scratching to understand how the new one operates because it is functionally identical to the old one.

An interface is a contract which guarantees a certain mode of operation and so, once published, an interface should never change. This is the rule which is broken by thousands of programmers every day and which is the cause of countless problems of incompatibility where absolute compatibility should be guaranteed.

Understanding how an interface works.

When we design a class, we have absolute free choice as to how we implement the methods in it. Because the world is a diverse and wonderful place, we can almost guarantee that our class does things differently to many others that may have been created elsewhere but which do essentially the same job. We may or may not design our class to operate in a standard way but at some point in its lifetime a decision may be taken to render that class compatible with a standard interface.

Take the following class written in C#:

    public class MyRadio

    {

        public void SwitchOn()

        {

        }

 

        public void SwitchOff()

        {

        }

 

        public void Volume(double level)

        {

        }

 

        public void FrequencySet(double Hertz)

        {

        }

    }

 

We can safely ignore the implementation of the various methods in the class so nothing is shown. We could also have chosen any other of hundreds of ways to define our methods or properties. Take a moment then to imagine how the compiler sees this class is used.

        public static void Main()

        {

            MyRadio mr = new MyRadio(); //Create a new radio

            mr.SwitchOn();              //Turn it on

            mr.FrequencySet(191000);    //Set the frequency

            mr.Volume(5);               //And the volume at half

        }

 

When the compiler sees the invocation of the various methods, such as SwitchOn, FrequencySet and Volume it uses a table in the class to find the correct address to call and so the program which uses the radio is able to call the correct program addresses.

Now we’ll imagine that the world’s most important online music company publishes an interface that enables you to add your radio to their player. They have no knowledge of your radio and they don’t care. The interface they publish is called IRadio and looks like this:

    public interface iRadio

    {

        bool Power { get; set; } //Used to set or get the power state of the radio

        void Volume(int v); //Set the playback volume in percentages of maximum where 0=silent and 100=full volume

        void Frequency(double f); //Set the frequency in kilohertz, eg. 191 for 191000 hertz

    }

 

Now, to be able to participate in their online entertainment system and earn cash by having your users use their services all you need to do is implement their interface like so:

    public class MyRadio : IRadio

    {

        public void SwitchOn()

        {

        }

 

        public void SwitchOff()

        {

        }

 

        public void Volume(double level)

        {

        }

 

        public void FrequencySet(double Hertz)

        {

        }

 

        bool powerState;

 

        public bool Power

        {

            get

            {

                return powerState;

            }

            set

            {

                powerState = value;

                if (value)

                    SwitchOn();

                else

                    SwitchOff();

            }

        }

 

        public void Volume(int v)

        {

            Volume(1.0 / 100 * v);

        }

 

        public void Frequency(double f)

        {

            FrequencySet(f * 1000);

        }

    }

 

Now, your radio is compatible with their radio specification and will work with their systems earning you piles of cash.

The compiler effectively sees two sets of method addresses on the same class. The ones provided by the class in its public declaration and the one added to the class by the interface definition.

Dangers of modifying interfaces

One day your support department begins to get calls that your radio is useless and doesn’t work. They will never use your lousy services again and you can go poke your software where the sun doesn’t shine and oh, by the way, I want my money back! This is puzzling because you haven’t changed a thing.

A quick diagnostic shows that the world’s biggest online music corporation hired a novice programmer who worked hard to “improve” their radio system and changed the IRadio interface.

As a result, your radio is incompatible, as are the radios of all the companies that participate in the online player so there are a ton of unhappy users and customers this morning all because the IRadio interface was modified. Here’s the modification:

    public interface IRadio

    {

        bool Power { get; set; } //Used to set or get the power state of the radio

        void Volume(int v); //Set the playback volume in percentages of maximum where 0=silent and 100=full volume

        void ScanUpToNextStation();

        void ScanDownToNextStation();

    }

 

As you can clearly see, this is an IRadio interface but it really isn’t the IRadio interface so now, not a single radio player on the system is working.

Needless to say, the novice programmer is roundly chastised with good humour and the more mature programmers tell the little wag very kindly that the right way to do it was to add another interface

    public interface IRadioScanControls

    {

        void ScanUpToNextStation();

        void ScanDownToNextStation();

    }

 

Given this new interface you can still participate in the IRadio scheme with total compatibility. You could, if you wish simply leave your software as it was and not bother with the new controls. However, you can also implement the new interface and add the new functionality because adding that interface definition does nothing more drastic than add another set of method indirections to the class which the compiler can find if it needs to.

    public class MyRadio : IRadio, IRadioScanControls

    {

        public void SwitchOn()

        {

        }

 

        public void SwitchOff()

        {

        }

 

        public void Volume(double level)

        {

        }

 

        public void FrequencySet(double Hertz)

        {

        }

 

        bool powerState;

 

        public bool Power

        {

            get

            {

                return powerState;

            }

            set

            {

                powerState = value;

                if (value)

                    SwitchOn();

                else

                    SwitchOff();

            }

        }

 

        public void Volume(int v)

        {

            Volume(1.0 / 100 * v);

        }

 

        public void Frequency(double f)

        {

            FrequencySet(f * 1000);

        }

 

        public void ScanUpToNextStation()

        {

            //Do up scanning here...

        }

 

        public void ScanDownToNextStation()

        {

            //Do down scanning here...

        }

    }

 

Summary

An interface is an UNBREAKABLE CONTRACT OF COMPATIBILITY between two systems.

Once published, an interface must never change.

An interface adds a new table of method or property indirections to a class. We can add as many such tables as we like.

Some languages allow one interface to inherit from another in the same way that classes can inherit from bases. Tough this is used often, you must understand that inheriting an interface forces the class adopting the interface to fully implement all methods and properties of all inherited interfaces. This can become an unnecessarily hefty task and simply defining a new and separate interface is usually the best option. An example of utterly horrible interface inheritance is the .Net IBindingList interface which inherits several others and is an utter pain to use.  

 
Sponsored By
DaraizeTechnologies.com
Bob Powell

Create your badge

Copyright © Bob Powell 2000-2012.  All rights reserved.