Interfaces

An interface is a description of the actions that an object can do... for example when you flip a light switch, the light goes on, you don't care how, just that it does. In Object Oriented Programming, an Interface is a description of all functions that an object must have in order to be an "X". Again, as an example, anything that "ACTS LIKE" a light, should have a turn_on() method and a turn_off() method. The purpose of interfaces is to allow the computer to enforce these properties and to know that an object of TYPE T (whatever the interface is ) must have functions called X,Y,Z, etc.

Interfaces in Object Oriented Programming Languages

An interface is a programming structure/syntax that allows the computer to enforce certain properties on an object (class). For example, say we have a car class and a scooter class and a truck class. Each of these three classes should have a start_engine() action. How the "engine is started" for each vehicle is left to each particular class, but the fact that they must have a start_engine action is the domain of the interface.

The syntax of an Interface

An interface has a very simple syntax that looks very much like a class definition... public interface XYZZY. Inside the {} of the interface is a list of functions that must be found in any object that purports to "follow" the interface.

Interfaces are placed in their own files which have the same name as the interface (are Capitalized) and end with the familiar language extension (e.g., ".as"). The following interface would be placed in a "Vehicle.as" file.

Here is an example of the Vehicle interface referred to above (only a partial definition).

        
          package 
          {
             public interface Vehicle
             {
                 // NO data VARIABLES are allowed in an interface
                 // only function PROTOTYPES


                 /**
                  * Comments...
                  * Anything that wants to be a "Vehicle" must, implement this function
                  */
                 function start_engine() : void;

             
             }
          }
        
      

Below are enumerated the differences between an interface and a class.

  1. No VARIABLES are allowed to be declared by the interface.

    An interface is about actions that are allowed, not about data or implementation of those actions.

  2. The keyword public is not placed in front of the function prototypes. By definition, all functions listed in an interface must be public functions.

  3. There is no code after the function prototype. The normal {} are replaced with a single semi-colon.

Implementing an Interface

To tell the computer that a new class that you are writing will fulfill all the requirements (implement all the functions) of an interface, you must use the keyword implements in the same location where you can use the keyword extends.

Here is an example of a Car Class which implements the Vehicle definition.

        
          package 
          {
             public class Car implements Vehicle
             {

                 /**
                  * Comments...
                  *
                  * Here is how we start our car.  This function is mandated by the Vehicle
                  * interface.
                  */
                 function start_engine() : void
                 {
                   // code to start the engine of the car...
                 }
             
             }
          }
        
      

Remember: While all functions in the interface must be implemented in the class, you can also create any other functions you want for that class.

Polymorphism applied to Interfaces

What is the power of the interface? The power is that once we have a number of classes which implement the interface, from some point of view, they are equivalent. For example, say we want to create a Car and a Truck, but all our program wants to do is "start" them and "drive" them. To our program's "point of view" they are just Vehicles.

Below are examples showing how we would write the code without interfaces, with interfaces, and then with a generic arrays of "Vehicles".

With out Interfaces

            
          // Main Actions
          var car   : Car = new Car();
          var truck : Truck = new Truck();
          
          car.start_engine();
          truck.start_engine();
          
          car.drive();
          truck.drive();
            
          

With Interfaces

            
          // Main Actions
          var vehicle1   : Vehicle = new Car();    // here the only difference is the TYPE of each variable is the same!!!!
          var vehicle2   : Vehicle = new Truck();
          
          vehicle1.start_engine();
          vehicle2.start_engine();
          
          vehicle1.drive();
          vehicle2.drive();
            
          

Using an array and polymorphism

            
          // Main Actions
          var vehicles : Array = new Array();
          
          vehicles.push( new Car() );    // Assume our program is modeling a game or traffic simulation
          vehicles.push( new Car() );    // The Cars and Trucks that we are modeling can be created in
          vehicles.push( new Truck() );  // an arbitrary matter.  Normally we would have to create separate
          vehicles.push( new Car() );    // arrays for Cars, Trucks, etc.  But because the are all vehicles
          vehicles.push( new Truck() );  // we can put them in a single array of Vehicle.
          vehicles.push( new Truck() );
          vehicles.push( new Truck() );
          vehicles.push( new Car() );
          vehicles.push( new Truck() );
          vehicles.push( new Car() );
          vehicles.push( new Bicycle() ); // assume Bicycle is also a Vehicle...
          vehicles.push( new Car() );


          // Later on in the program, we want to start all the cars...
          // We can use GENERIC programming (we don't care if they are cars, trucks, bicycle, etc, just that they are vehicles).

          for each (var item : Vehicle in vehicles )
          {
            item.start_engine();
            item.drive();
          }
            
          

The final example above shows the concept of Polymorphism. Polymorphism is the idea that an compile time (coding time) we don't know (and often can't know) what the actual type of object inside a variable will be. In the vehicles array above, we don't know if vehicles[i] is a car, truck, bicycle, etc. In computer languages without polymorphism, we wouldn't be able to do anything with these objects.

With polymorphism, the computer remembers what each is and when we say: "item.start_engine();" the computer decides, if this item is a truck then call "truck.start_engine()", if this item is a car, call "car.start_engine()", if this object is an XYZZY, call "XYZZY.start_engine();"

Polymorphism save the programmer a lot of time and effort in coding up "exceptional" conditions. The computer does the work for us, a) remembering what each object really is, and then b) at run time, invoking the actual function associated with the current object.


The specific Type under the Interface

Sometimes, you will want to use a function specific to an underlying type. For example, a dump truck implements Vehicle, but additionally has a "raise_bed" function which dumps everything out of the back of the truck. In the following code, the dump truck is thought of by the computer as a Vehicle, and thus the code DOES NOT HAVE ACCESS to the raise_bed function.

        
          var vehicle : Vehicle = new Dump_Truck();
          
          vehicle.start_engine(); // ALLOWED: vehicle is a Vehicle and thus has the start_engine function
          vehicle.drive();        // ALLOWED: vehicle is a Vehicle and thus has the start_engine function

          // Compile Time Type error
          vehicle.raise_bed();    // NOT ALLOWED: while in reality (at run time) the vehicle variable
                                  //              will contain a Dump_Truck and thus this should be a legal
                                  //              operation, the compiler (at program time) only sees that
                                  //              vehicle is a Vehicle and the Vehicle class dose not
                                  //              have a raise_bed function.
        
      

But!!! you say, I (the programmer) know that this vehicle really is a Dump_Truck. How can I tell this to the computer.

The as keyword.

To override the computers type checking, you can "take charge" of your program and force the computer to treat the contents of the vehicle variable as a Dump_Truck. Here is the proper code

        
          var vehicle : Vehicle = new Dump_Truck();
          
          (vehicle as Dump_Truck).raise_bed();    //  ALLOWED: here the programmer overrides the type checking of the computer.

        
      

Warning: If the vehicle variable does not contain a Dump_Truck (the programmer made a mistake), then the entire program will "Crash" at this point.

You should strive not to use the as key word except when absolutely necessary. When we don't use it, we have the assurance of the computer that our types are correct. When we do use it, all we have is the programmers assurance, and programmers are often wrong.


Summary

Interfaces fulfill two goals:

  1. They allow the programmer to be more abstract when referencing objects (for example, var vehicle : Vehicle, can reference any car, truck, etc... anything that is a vehicle (and not care what type it is.) This occurs at "program time".

    When the vehicle.start_engine() function is invoked, the correct function associated with the real object is actually used. This occurs at "run time".

  2. They require the programmer to create specific functions that are expected in an implementing class when it implements an Interface.

    Again, this allows all objects in a "set" of like objects to be treated based on the "high level" type of the set, rather than on the specific type of the individual object.



Back to Topics List