For the past few hours I have been pouring through hundreds of internet articles, blogs and posts in various forums regarding interfaces.

I get a general idea that it is basically a class with no implementation at all...a "skeleton" if you will.

I was hoping for an a-ha! moment that never came. This is my last ditch effort here.

What exactly is the usefulness of making interfaces?

I've read that it makes code more clean and easier to manage, but I fail to see how it would ever do that. Changing a public class that is used by many other methods or classes seems to be much MUCH more manageable than editing a "template" and then having to edit (maybe) every single instance of that template.

Also, it provides no information on it's function.

I mean an interface like this:

public interface ICopy
{
public void CopyMethod();
}

Could be implemented in any way a programmer wants like this:

public class FileManipulation : ICopy
{
public void CopyMethod()
{
//code to copy files
}
}

but it could also be implemented like this:

public class MakePrankCalls : ICopy
{
public void CopyMethod()
{
//code to use a modem and dial random numbers then play a .wav file to prank them
}
}

I mean it basically means nothing right?

The definition of an interface (in computer science) is "a point of interaction between two components." I fail to see how an interface in C# achieves this at all...

It seems to me that if I look at source code from someone that uses interfaces, I cannot rely on the fact that simply because an interface is used on a class, that it was used correctly (like my sample above) right?

I'm really hoping that someone can set me straight here and say something like "no, no, no! your missing the fact that __________________."

Anyone?

Recommended Answers

All 24 Replies

Interfaces are extremely useful, and there are many examples why.

Taking your example one step further, you can then have another class that does this:

public class Copier
{
private ICopy copy;

public Copier(ICopy copy)
{
  this.copy = copy;
}

public void MakeCopy()
{
  copy.CopyMethod();
}
}

Now the Copier class doesn't care how the CopyMethod is implemented. This means that you can decide what gets passed to your Copier object via the constructor, and it could be a FileManipulation object or a MakePrankCalls object, or some other implementation of ICopy interface.

This is just a simple example, but as your classes get more complex, this is extremely useful.

Hmmm...

too many copy variables and...too many copy words!

I think I understand what you mean though...that a-ha moment is approaching I think...

so would it be a fair statement to say interfaces are useful, but are only useful when a class implements the interface and a different, 3rd class calls what it needs from the second class?

Bad wording I think, let me try saying it a different way...in order to use an interface correctly, one would implement the interface on a class and the properties, methods etc... inside the class (or multiple classes I suppose) could be called by a different method in a different class?

You basically make a template with an interface, and build classes off of that interface to use elsewhere...right?

Would you ever implement an interface on a class that contained code that would execute on it's own?

For example, would it ever be useful to implement an interface on say, the

Program

class? (you know, the entry point for the application?) Or on the class that your main application form opens under?

Seems like it might be better to implement the interface on a different class and then just call whatever you needed from that class to the

Program

class or the main application form.

I still do not see how it could help improve code maintainability though...If my application uses an interface to build class objects and in the future that interface needs to change...I have to go back and change ALL of the classes that implement that interface and make sure they comply...interfaces require that all members be declared, even if they aren't "used" (like declaring

CopyMethod() {}

). That seems like it would be a total nightmare.

Maybe I'm wrong...I'm not totally convinced that they have much use other than creating a skeleton for a method, when the method could be made alone without the interface and saving yourself one extra step.

I guess I'll just have to play with it and see what I come up with.

Thanks for the info!

Member Avatar for embooglement

Alright, here's an example of how interfaces could be used:

interface Animal
{
   public void MakeNoise();
}

class Cow : Animal
{
  public void MakeNoise()
  {
    Console.WriteLine("Moo");
  }
}


class Dog : Animal
{
  public void MakeNoise()
  {
    Console.WriteLine("Bark");
  }
}

class Farm
{
  public List<Animal> animals;
  
  public Farm()
  {
    animals = new List<Animal>();
  }
  public void AddAnimal(Animal argAnimal)
  {
     animals.Add(argAnimal);
  }
}

class Program
{
   public void Main()
   {
     Farm farm = new Farm();
     farm.AddAnimal(new Cow());
     farm.AddAnimal(new Dog());
   }
}

Alright, so basically this creates an interface called Animal. This interface is used to derive new classes which MUST provide implementation for the functions in the interface (in this case, it's a function that tells the animal to make noises).

Because all classes that derive from Animal provide all of the functions declared in Animal, one can invoke the functions in Animal from a derived class without actually knowing what the animal is. This cuts out a lot of extraneous code. For instance, the AddAnimal function in Farm. Without an interface for animals, one would have to overload the function for each kind of animal needed. Also, this make AddAnimal extensible. One could create a new class called Bear, derive it from Animal, and then one could instantly add it to farm.animals using AddAnimal, without needing to add more code to Farm.

The interface also allows all animals to be grouped together, such as in farm.animals. One could do a foreach, like this:

foreach(Animal a in farm.animals)
{
  a.MakeNoise();
}

The other benefit of using interfaces is it allows the implementation to be determined by a function, and can vary depending on the conditions, allowing one to do something like this in:

class God
{
  public static Animal MakeAnimal(string AnimalType)
  {
    if (AnimalType == "cow") return new Cow();
    if (AnimalType == "dog") return new Dog();
    else return null;
  }
}

Obviously this example is trivial, but there are examples when it is very much appropriate to use interfaces. For instance, DirectX uses interfaces to implement COM objects. These objects are created using functions similar to God.MakeAnimal in that they decide which instance of a COM object class is most appropriate for a given computer, which may change from user to user.

I hope I explained that well, and I apologize for any syntax mistakes I may have made. I'm a C++ programmer by trade, and only have minimal experience with C#.

commented: very well written +3

I mean it basically means nothing right?

Which is the same for any method at all. You can call a method anything you like, and it can do anything you like. By convention and unwritten agreement programmers try to name methods so that someone reading the code can make a good guess at what it does. This helps people who might have to come along after you (or you might be the one coming along after someone else) maintain your code.

People who violate this convention tend to get bad performance reviews and, ultimately, unemployed. No one wants to deal with that type of code.

Member Avatar for embooglement

To the OP: Do you understand what virtual functions do?

It's late so bear with me...

embooglement,

Let me make sure I understand this implementation by stepping it out:

1. You create an interface (Animal) and define in that interface what is required for any classes to be derived from that interface (MakeNoise()).

2. You then create classes that are derived from the interface (Cow and Dog). You can derive nearly an unlimited number of classes from the interface, all of which follow the same interface scheme, but are different (Cow.MakeNoise() returns Moo and Dog.MakeNoise() returns Bark).

3. You can then create any number of other classes that are not derived from the interface (Farm) but can use instances of the classes that are derived from the interface.

That's honestly as far as I get before I start to get lost.

How about this...tell me if this is a good example of a situation to implement an interface:

A program that supports retrieving data from a few different data sources (MS Access files or an SQL server). I ask this because I have something that does that now...would an interface be useful in a situation like this?

If an interface wouldn't be of help here...I really am lost still to find a situation where one would be useful. Farm animals are cute and the example you provided makes sense...but I can't think of a real situation where something like that would ever be used. Maybe I just haven't gotten that far yet.

Check this out:

/// <summary>
        /// Converts the long ConnectionType value into the connection method needed to access the data.
        /// </summary>
        /// <returns>Returns the connection method needed to access the data.</returns>
        private string GetConnectionType()
        {
            //initialize the connection type that is set
            string ConnectionType = ConnectionVariables.ConnectionType;
            
            //determine what kind of connection it is
            switch (ConnectionType)
            {
                case "Microsoft SQL Express Server (Default)":
                    {
                        //we need an SqlConnection Connection
                        return "SqlConnection";
                    }
                case "Microsoft Access Database File (.accdb)":
                    {
                        //we need an OleDbConnection Connection
                        return "OleDbConnection";
                    }
                default:
                    {
                        //can't determine the connection type
                        return "Unknown";
                    }
            }
        }

        /// <summary>
        /// Builds a skeleton connection for use in the application or the DataBase Management System
        /// </summary>
        /// <returns>Returns a connection object. The object must be cast when used.</returns>
        public Object GetConnection()
        {
            //a connection to the data source was requested
            //find out what kind of connection we need to build
            string ConnectionMethod = GetConnectionType();

            //make sure we know the connection method
            if (ConnectionMethod == "Unknown")
            {
                //we don't know what kind of connection it is, this file might need to be updated
                //return false to indicate the method failed
                return false;
            }
            
            //try to build a connection based on the connection method
            switch (ConnectionMethod)
            {
                case "OleDbConnection":
                    {
                        //initialize the string builder
                        OleDbConnectionStringBuilder ConnectionStringBuilder = new OleDbConnectionStringBuilder();

                        //set the data source
                        ConnectionStringBuilder.DataSource = ConnectionVariables.DataSource;

                        //set persist security info
                        ConnectionStringBuilder.PersistSecurityInfo = ConnectionVariables.PersistSecurity;

                        //set user id (if set)
                        if (ConnectionVariables.UserName != null || ConnectionVariables.UserName != "")
                        {
                            ConnectionStringBuilder.Add("User ID",
                                ConnectionVariables.UserName);
                        }

                        //set password (if set)
                        if (ConnectionVariables.Password != null || ConnectionVariables.Password != "")
                        {
                            ConnectionStringBuilder.Add("Jet OLEDB:Database Password",
                                ConnectionVariables.Password);
                        }

                        //we have our connection string now, lets build the connection
                        OleDbConnection Connection = new OleDbConnection(ConnectionStringBuilder.ConnectionString);

                        //clean up
                        ConnectionStringBuilder.Clear();

                        //return our connection
                        return Connection;
                    }
                case "SqlConnection":
                    {
                        //initialize the string builder
                        SqlConnectionStringBuilder ConnectionStringBuilder = new SqlConnectionStringBuilder();

                        //set the data source
                        ConnectionStringBuilder.DataSource = ConnectionVariables.DataSource;

                        //set user id and password if integrated security is not going to be used
                        if (ConnectionVariables.IntegratedSecurity == false)
                        {
                            //we are not using Windows Authentication, the user has to provide a user id
                            //and password
                            
                            //set user id
                            ConnectionStringBuilder.UserID = ConnectionVariables.UserName;
                            
                            //set password
                            ConnectionStringBuilder.Password = ConnectionVariables.Password;

                            //set integrated security (Windows Authentication)
                            ConnectionStringBuilder.IntegratedSecurity = ConnectionVariables.IntegratedSecurity;
                        }
                        
                        //set integrated security if user id and password are not going to be used
                        if (ConnectionVariables.IntegratedSecurity == true)
                        {
                            //we are using Windows Authentication, the user does not need to provide a user id
                            //or password

                            //make sure the user id key is not in the connection string
                            ConnectionStringBuilder.Remove("UserID");

                            //make sure the password key is not in the connection string
                            ConnectionStringBuilder.Remove("Password");

                            //set integrated security (Windows Authentication)
                            ConnectionStringBuilder.IntegratedSecurity = ConnectionVariables.IntegratedSecurity;
                        }

                        //if the initial catalog is defined, set it
                        if (ConnectionVariables.InitialCatalog != null || ConnectionVariables.InitialCatalog != "")
                        {
                            //set the initial catalog
                            ConnectionStringBuilder.InitialCatalog = ConnectionVariables.InitialCatalog;
                        }
                        else
                        {
                            //initial catalog isn't defined, remove the key
                            ConnectionStringBuilder.Remove("InitialCatalog");
                        }

                        //we have our connection string now, lets build the connection
                        SqlConnection Connection = new SqlConnection(ConnectionStringBuilder.ConnectionString);

                        //clean up
                        ConnectionStringBuilder.Clear();

                        //return our connection
                        return Connection;
                    }
                default:
                    {
                        //this should never happen because we already determined that we know what type of
                        //connection method is needed, but just in case
                        return false;
                    }
            }
        }

An interface would be useful in your database situation. You create the interface that specifies what needs to be sent to methods and what comes back from these methods. You then create classes for each storage type you wish to use, all of which implement the interface.

This way your code doesn't care how the data is stored, just that it can use an object that has a specific interface. The data could be in SQL Server, Access, text files, etc. Doesn't matter to the calling code.

Member Avatar for embooglement

Honestly, I have no idea about data base programming like that. I'm a game programmer. I've used or seen interfaces used to implement every thing from graphics devices, weapon classes, enemy classes, etc.

I guess the best way to explain it would be to say that they're used when you need a class that provides general functionality, but the exact implementation can't be know at compile time. For instance, with DirectX, you have to create an instance of a graphics device to access the graphics card. In reality, there are tons of different graphics cards, many of which probably require different code to do the same thing. Using an interface allows me to ignore these differences completely, and leave the exact implementation to DirectX. This device can then be used to draw things on screen with a function called Present(). Now, the exact details of the Present() function can vary greatly depending on the user's version of DirectX, and the kind of graphics card they have. By having a device interface, and then encapsulating it's creation in a function, DirectX is able to make sure that the correct kind of class is used, while I may be blissfully ignorant of the fact that there are multiple classes at all.

Interface programming is certainly useful, no doubt about it, but it's not necessarily useful for everything. It really depends on context.

embooglement,

missed your other question. I've never even heard of virtual functions. I'll have to research that. Are they related to interfaces?

Member Avatar for embooglement

They are the corner stone of interfaces. in fact in C++ there is no interface keyword, you have to use virtual functions to mimic the functionality of them.

embooglement,

I've been reading your post over and over and doing more self-education on interfaces...I wonder though...

How do you deal with a multiple (possibly dynamic) number of instances of the same class that are initialized with an interface?

Like for example...

Changing your code from:

class Program
{
   public void Main()
   {
     Farm farm = new Farm();
     farm.AddAnimal(new Cow());
     farm.AddAnimal(new Dog());

     foreach(Animal a in farm.animals)
     {
       a.MakeNoise();
     }
   }

}

to:

class Program
{
   public void Main()
   {
     Farm farm = new Farm();
     farm.AddAnimal(new Cow());
     farm.AddAnimal(new Cow());
     farm.AddAnimal(new Dog());

     foreach(Animal a in farm.animals)
     {
       a.MakeNoise();
     }
   }

}

adds a second cow to the list. Great...how can I tell cow #1 apart from cow #2?

What if in my foreach statement I only want the second cow to moo and not the first one?

Or in a dynamic situation where a loop is used to add animals to a list and the number of times a loop is run depends on user input...at compile time we don't know what number the user will put in. It could be 0 or a million. How could we modify any of those number of instances?

What if we had the interface for Animal set up like this:

interface Animal
    {
        string NoiseToMake { get; set; }
        string CreateANoiseToMake();
        void MakeNoise();
    }

and each class instance could be implemented differently like this:

class Dog : Animal
    {
        private string _noiseToMake;

        public string NoiseToMake
        {
            get
            {
                 return _noiseToMake;
            }
            set
            {
                 _noiseToMake = value;
            }
        }

        string CreateANoiseToMake()
        {
            //some code to generate a random noise to make from a list of noises
            //but only sets the NoiseToMake string if it's empty, if it already
            //has a noise, it returns the same string and won't change it.
        }

        public void MakeNoise()
        {
            CreateANoiseToMake();
            Console.WriteLine(NoiseToMake);
        }
    }

class Program
{
   public void Main()
   {
     Farm farm = new Farm();
     farm.AddAnimal(new Cow());
     farm.AddAnimal(new Dog());
     farm.AddAnimal(new Dog());

     foreach(Animal a in farm.animals)
     {
       a.MakeNoise();
     }
   }

}

Now we don't know what kind of noise the animals will make because it's randomly generated (only once though) when the MakeNoise() method is called. In the example we have 2 Dogs in the list...if the first one makes a "bark" noise and the second one makes a "growl" noise, how can we pick out the "bark" one from the other one without iterating through the entire list of animals and calling MakeNoise() on them all until we get the one we want.

With only 3 animals in the list, one not even being a Dog, iteration might be okay, but if the Main() method contained a loop to add x number of animals (both the type of animal (dog, cow etc...) and the number of each type to add) we could end up with thousands or millions of Dogs! I've never benchmarked iteration methods, but I would imagine it might take a while to call MakeNoise() on thousands of animals in a list, especially if MakeNoise() wasn't as simple of a method as it is in the example.

I guess the big question is, if we have multiple instances of classes that implement an interface (like 100 Dogs), and I want to change something about Dog #28, do I need to include in the interface Animal a public id integer and a method to make sure that integer is unique?

Even if I did something like that though, that would be assuming that the animals were added to the list in order of the id...and that might not be true, considering a user could add or remove animals at will from the list through a different method. So I guess the question still stands...how do I pick out Dog instance #28 from all the rest of the Dogs when Dog #28 might not be the 28th item (err 27th) in the list of animals on the farm?

Member Avatar for embooglement

The interface is merely a base class that declares functions that must be implemented. All of the normal base class rules apply. So each "new Dog()" creates an entirely new and unique instance of a Dog. The only thing the interface does is guarantee that MakeNoise, CreateNoiseToMake, and NoiseToMake must exist in the derived class. And because each of these is virtual, they can be called from a base class without needing to know what the derived class is.

This might help a bit more. Say we have an Animal interface, which declares that each animal must have a MakeNoise method, and a Dog class, which implements this method, but also has a size and name property:

interface Animal
{
  string MakeNoise();
}

class Dog : Animal
{
  string MakeNoise() { return "bark!" }
  int Size { get; set; }
  string Name { get; set; }
}

This means that we can access any methods of Animal from a derived class, but not any of those declared in the derived class. Like so:

Animal someAnimal = new Dog(); 

typeof(someAnimal); // this returns Animal, not Dog. 

someAnimal.Name = "Steve"; // Can't do this, Animal has no Name method
someAnimal.Size = 42; // Can't do this either!
someAnimal.MakeNoise(); // can do this, because Animal has MakeNoise method

So, and I doubt I'll explain this clearly, despite the fact that someAnimal is an Animal, it can be used to call some methods in Dog because Dog adheres to the Animal interface, but it can only call those that are in Animal, it has no way of knowing what other functions exist in Dog.

Now, this might seem pointless still, but it really isn't. In theory, each kind of animal one could model with classes is going to have a certain list of properties and actions that they can do, no matter what the animal is. That's the basis of inheritance. By having an interface that declares these properties and actions, one can treat each animal being modeled as if they were instances of a single class called Animal.

Now, the other important thing to note is "typeof(someAnimal)" returning Animal. had the line been something like "Dog someAnimal = new Dog();" than the typeof() would have returned Dog. Using the interface in no ways impedes you from using Dog as any other class.

I hope that helps. Honestly, I don't think interfaces make much sense unless you really understand the underlying code, which involves knowing how virtual functions work, and what base pointers are. One of the biggest benefits of C# is that it hides that kind of stuff from the programmer, but in some cases it also impedes the ability to understand the mechanics behind something.

embooglement,

I think I am starting to get the idea behind interfaces, and I can see a few instances where it could be useful. Having many classes that are related in some way, but perform slightly different functions would be an example. Maybe interfaces for performing mathematical computations that all require the same number and type of variables but produce different outcomes could be a situation.

But more so, it seems like, unless two classes are going to potentially interact with each other in some way, interfaces aren't necessary. Is that right?

Even in your original example with the cow and dog...the only reason (I imagine) that a programmer would want to put those objects into a list together is because they have something in common, and somewhere along the line they may interact with each other, like having a dog chase a cow and produce a result (the dog catches the cow, or the cow escapes) and then having a different method interpret that result and either perform additional methods or return the result to a variable for use later; or with mathematical computations, having one mathematical class depend on another to achieve a final solution.

I could also see using interfaces to potentially "protect" certain methods from throwing exceptions and/or guarantee results of a certain kind, for example If a method such as public Animal myMethod(Animal parameter1, Animal parameter2){ //do stuff return AnimalObject } was implemented, passing a string, integer or any type other than the type "Animal" wouldn't work...preventing the programmer from using an incorrect method and preserving the methods return integrity. But again, a method like that could possibly require one or two different types of Animal objects to interact.

Member Avatar for embooglement

Yeah, you're on the right track. A couple things though: the instances of the derived classes don't necessarily have to interact, though it certainly helps to have an interface if that's something you want. The example I gave where the animals were stored in a list was really just to show how it could cut down on code. Instead of having a list of Dogs, Cows, and every other animal, you can have on list of animals that stores every kind of animal. The other benefit is that the user can write new implementations of an interface. For instance, let's say the Farm class was in a .dll, and therefore couldn't be changed. If it gave each animal it's own list, the number of types of animals in the farm would be limited. So while the farm could have cows and dogs and pigs and what have you, it couldn't account for every animal a user may want to add. By using a common animal interface, any one could easily write a class for peacocks or elephants, and put those into the farm as well, and without having to alter the farm class.

I see, allowing for another programmer (after my application is complete) to write a .dll plugin or whatever, to add a new class of animal to the list can be done my accessing the public Animal interface and complying with it, so long as my application allowed such a thing.

Besides allowing other programmers or users to programatically add to the Animal type, why would a programmer use an interface?

If, for instance, I didn't want an outside user to add new Animals, why would I want to implement interfaces in my application? Do you have any real-life specific examples...I don't need to see code, just a synopsis of a situation besides adding things to a list.

Member Avatar for embooglement

Well there's no need for the interface to public. You could certainly mark it as private. But the other use would be like what I talked about earlier with DirectX graphics devices. To create one you call a function called CreateGraphicsDevice or something, pass it a bunch of arguments describing what you're looking for, and it returns an instance of an appropriate class, which you store in the interface. That way you don't need to know which specific class is most appropriate for your situation, and being that different computers would require different classes, having one interface is useful because it means you can treat each one of these classes as if they were the same thing. That kind of factory functionality is the other major benefit of interfaces I've seen.

I've never used DirectX or anything similar so the concept sort of escapes me completely, but I could pretend... :)

One thing I don't understand is...how can a class method that implements an interface return a specific object if it doesn't know what object type to return?

When I create a method the standard that I follow is if a method returns something (anything) that type needs to be declared. (or you could use the Object type and cast it later)

For example:

public SqlConnection MakeSqlConnection(some parameters that a sql connection needs)
  { //code to make a SqlConnection
    return a built connection
  }

In your interface, if you define a bunch of methods to build every possible connection (or DirectX device) type you want to support that means every class that uses it would need to define methods for all of those as well...that doesn't seem very logical.

Also, did I understand you correctly that you can define classes (methods, properties, events etc...) inside of an interface definition? I don't get it? How? I didn't think interfaces could contain classes, only the skeleton of a class?

What you are talking about with the DirectX solution seems very similar to the whole reason I looked into interfaces to begin with. I am developing an application that can support various types of data sources (but only uses one at a time), each data source needs to be communicated with in a different way, but most have a certain set of common functions, abilities and parameters that are needed...some have more, some have less. I would LOVE to have a single method that could interface with all of the different data sources. This sounds similar to what you are doing...one method (CreateGraphicsDevice) examines the parameters (possibly describing the user's graphics hardware setup) and based on that input creates the appropriate instance of a class (that probably defines how your application should interact with the graphics hardware).

I guess where I get lost is...how is a class instance returned to be used and how would a programmer interact with it?

I know that all classes that utilize an interface have the same MINIMUM structure...but how would you interact with a method, property or event that is in addition to the minimum structure?

Take our Dog Class again.

class Dog : Animal
{
  string MakeNoise() { return "bark!" }
  int Size { get; set; }
  string Name { get; set; }
}

what if we have another animal

class Cat : Animal
{
  string MakeNoise() { return "Meow" }
  int Size { get; set; }
  string Name { get; set; }
  string Purr() { return "Purr" }
}

if we have a method that returns an object of type Animal, and based on the parameters it selects the Cat class and returns an instance of it. A dog can't purr, just the cat can...when we start using the class that is returned, how do you set it up to be able to use the Purr() method if the cat class is returned? Do you just implement a bunch of if/then/else statements to determine the class that was returned so you can interact with it?

Member Avatar for embooglement

See, I've never done any data programming like that, so we're really in a pickle aren't we?

Alright, here I go; your last paragraph is pretty much right. If you returned an Animal object, the only things that could directly be used are things declared in Animal. That said, you can type cast it back into whatever the original Animal was, but you would either need to know what kind of Animal it is before hand, or set up a mechanism to determine an appropriate conversion. The Animal object is referring to a complete Cat or Dog instance, so that information isn't lost, you just need too tell the compiler what kind of object to treat it as.

In terms of data programming, you could do something like the following. Now, as I said before I'm a C++ programmer, and I'm kind of sleepy, so this probably isn't going to be the correct syntax, but the concept should still show. My apologies.

enum DataTypeID
{
   XMLDataID,
   SQLDataID,
   TXTDataID
}

interface IData
{
   public void Load(string filename);
   public Buffer GetBuffer();
   public string ToString();
   public DataTypeID GetDataType();
}

class XMLData : IData
{   
   public Buffer MyBuffer { get; set; }

   public void Load(string filename) { // load XML into MyBuffer }
   public Buffer GetBuffer() { return MyBuffer; }
   public string ToString() { return MyBuffer.ToString() }
   public DataTypeID GetDataType() { return DataTypeID.XMLDataID; }
}

class SQLData : IData
{   
   public SqlConnection MyConnection { get; set; }
   public Buffer MyBuffer { get; set; } 
  
   public void Load(string filename) { // set the connection to filename... I guess? I don't know SQL at all }
   public Buffer GetBuffer() { return MyBuffer; }
   public string ToString() { return MyBuffer.ToString() }
   public DataTypeID GetDataType() { return DataTypeID.SQLDataID; }
}


class TXTData : IData
{   
   public Buffer MyBuffer { get; set; } 
  
   public void Load(string filename) { // load file as text }
   public Buffer GetBuffer() { return MyBuffer; }
   public string ToString() { return MyBuffer.ToString(); }
   public DataTypeID GetDataType() { return DataTypeID.TXTDataID; }
}

class DataManager
{
   public static IData CreateData(string filename)
   {
      if // file is XML
      {  
          return new XMLData(filename);
      }
      if // file is SQL
      {
          return new SQLData(filename);
      }
      if // file is TXT
      {
          return new TXTData(filename);
      }
   }

   public static void DoStuffWithADataBufferOrSomething(IData someData)
   {
       Buffer buf = someData.GetBuffer();

       // do stuff with buf
   }
}

Again, database stuff isn't my strong suite. But I hope this example makes some sense.

embooglement,

Thank you so much for trying to explain this to me. But that last example threw me for a loop.

Let me try this.

Pretend we are going to build a race car game together. Forgetting all the stuff involved in that and only worrying about the cars and the race itself, take a look at this and tell me if you see any problems. VS doesnt show any, and it's not functional obviously, but I'm more into if this is a good implementation of interfaces and that the usage of the class instances is correct.

namespace AwesomeRaceCarGame
{
    /// <summary>
    /// Defines what all cars in our game need
    /// </summary>
    interface ICar
    {
        string Name { get; }            //the name of the car so a player can identify it
        int Speed { get; }              //the maximum speed of the car in kph
        int FuelCapacity { get; set; }  //how much fuel the car can hold in (litres)
        int Acceleration { get; set; }  //how fast the car accelerates in (kph/sec)
        int Deceleration { get; set; }  //how fast the car decelerates without braking and no acceleration 
                                            //in (kph/sec)
        int Weight { get; set; }        //how much the car weighs - use this to compute acceleration and 
                                            //deceleration (fuel weighs something, so we should include that)

        bool Drive(Object track, ICar opponent);    //the method that computes acceleration, 
                                                    //deceleration, weight and calls other 
                                                    //functions that would display the car's 
                                                    //position on a track as well as methods that
                                                    //would interpret clicks and key presses. It 
                                                    //would also control braking which would be a constant.
                                                    //returns true if the car wins the race
    }

    /// <summary>
    /// The components of a car. These could be things a player could buy with in-game cash from winning races
    /// to upgrade their car. These components would modify the components of a car instance.
    /// </summary>
    interface IComponents
    {
        string Name { get; }            //the name of the component so a player can identify it
        string Class { get; }           //the class that the component belongs to
        int Value { get; }              //the value that the component has
        int Cost { get; }               //how much the component costs in in-game cash
    }

    /// <summary>
    /// A red race car
    /// </summary>
    class RedCar : ICar
    {
        public string Name
        {
            get { return "Super Fast Red Car"; }
        }

        public int Speed
        {
            get { return 275; }
        }

        private int _FuelCapacity;

        public int FuelCapacity
        {
            get
            {
                return _FuelCapacity;
            }
            set
            {
                _FuelCapacity = value;
            }
        }

        private int _Acceleration;

        public int Acceleration
        {
            get
            {
                return _Acceleration;
            }
            set
            {
                _Acceleration = value;
            }
        }

        private int _Deceleration;

        public int Deceleration
        {
            get
            {
                return _Deceleration;
            }
            set
            {
                _Deceleration = value;
            }
        }

        private int _Weight;

        public int Weight
        {
            get
            {
                return _Weight;
            }
            set
            {
                _Weight = value;
            }
        }

        public void Drive(Object track, ICar opponent)
        {
            //code here for driving this car
        }
    }

    /// <summary>
    /// A blue race car
    /// </summary>
    class BlueCar : ICar
    {
        public string Name
        {
            get { return "Super Fast Blue Car"; }
        }

        public int Speed
        {
            get { return 300; }
        }

        private int _FuelCapacity;

        public int FuelCapacity
        {
            get
            {
                return _FuelCapacity;
            }
            set
            {
                _FuelCapacity = value;
            }
        }

        private int _Acceleration;

        public int Acceleration
        {
            get
            {
                return _Acceleration;
            }
            set
            {
                _Acceleration = value;
            }
        }

        private int _Deceleration;

        public int Deceleration
        {
            get
            {
                return _Deceleration;
            }
            set
            {
                _Deceleration = value;
            }
        }

        private int _Weight;

        public int Weight
        {
            get
            {
                return _Weight;
            }
            set
            {
                _Weight = value;
            }
        }

        public void Drive(Object track, ICar opponent)
        {
            //code here for driving this car
        }
    }

    /// <summary>
    /// A stanard size fuel tank for any race car
    /// </summary>
    class StandardFuelTank : IComponents
    {
        public string Name
        {
            get { return "Fuel Tank"; }
        }

        public string Class
        {
            get { return "FuelCapacity"; }
        }

        public int Value
        {
            get { return 75; }
        }

        public int Cost
        {
            get { return 0; }
        }
    }

    /// <summary>
    /// A huge fuel tank for any race car
    /// </summary>
    class HugeFuelTank : IComponents
    {
        public string Name
        {
            get { return "Huge Fuel Tank"; }
        }

        public string Class
        {
            get { return "FuelCapacity"; }
        }

        public int Value
        {
            get { return 150; }
        }

        public int Cost
        {
            get { return 100; }
        }
    }

    /// <summary>
    /// A standard speed engine for any race car
    /// </summary>
    class StandardEngine : IComponents
    {
        public string Name
        {
            get { return "MotorSmart 225"; }
        }

        public string Class
        {
            get { return "Acceleration"; }
        }

        public int Value
        {
            get { return 30; }
        }

        public int Cost
        {
            get { return 0; }
        }
    }

    /// <summary>
    /// A supercharged engine for any race car
    /// </summary>
    class SuperChargedEngine : IComponents
    {
        public string Name
        {
            get { return "MotorSmart 555"; }
        }

        public string Class
        {
            get { return "Acceleration"; }
        }

        public int Value
        {
            get { return 65; }
        }

        public int Cost
        {
            get { return 250; }
        }
    }

    /// <summary>
    /// Builds cars
    /// </summary>
    class CarAssembler
    {
        /// <summary>
        /// Builds a car based on different components
        /// </summary>
        /// <param name="selectedCar">A car type, red or blue</param>
        /// <param name="fuelTank">A fuel tank component</param>
        /// <param name="motor">A motor component</param>
        /// <returns>Returns the selectedCar parameter, with the new components added</returns>
        public ICar AssembledCar(ICar selectedCar, IComponents fuelTank, IComponents motor)
        {
            //lets make a car!
            
            //get the capacity of the fuel tank selected
            int NewFuelCapacity = fuelTank.Value;
            
            //get the acceleration speed from the motor selected
            int NewAcceleration = motor.Value;

            //upgrade our car
            selectedCar.FuelCapacity = NewFuelCapacity;
            selectedCar.Acceleration = NewAcceleration;

            //return our new car to the game
            return selectedCar;
        }
    }

    /// <summary>
    /// Returns a new instance of a race car
    /// </summary>
    class CarPicker
    {
        /// <summary>
        /// Depending on the players's selection, it will return an empty race car
        /// </summary>
        /// <param name="selection">The car the player selected</param>
        /// <returns>An instance of an empty race car</returns>
        public static ICar PickMe(string selection)
        {
            if (selection == "Super Fast Red Car")
            {
                return new RedCar();
            }
            if (selection == "Super Fast Blue Car")
            {
                return new BlueCar();
            }
            else
            {
                return null;
            }
        }
    }

    /// <summary>
    /// The tracks cars can race on
    /// </summary>
    class Tracks
    {
        /// <summary>
        /// Data on the first race track
        /// </summary>
        /// <returns>Returns an instance of RaceTrack1</returns>
        public Object RaceTrack1()
        {
            //code here to build the race track
            Object TrackData = null;    //set this to null, but it would actually return the information
                                        //about the track
            return TrackData;
        }
    }

    /// <summary>
    /// Controls aspects of a race
    /// </summary>
    class Race
    {
        //initialize our car assembler
        CarAssembler MakeCars = new CarAssembler();

        //before we can race, we need cars to race with
        /// <summary>
        /// This would be accessed through some sort of UI letting the user pick a car and components
        /// </summary>
        /// <param name="car">The car the user picked</param>
        /// <param name="fuelTank">The fuel tank the user picked</param>
        /// <param name="motor">The motor the user picked</param>
        /// <returns>Player 1's configured car</returns>
        public ICar Player1Car(ICar car, IComponents fuelTank, IComponents motor)
        {
            //Assemble Player 1's car
            return MakeCars.AssembledCar(car, fuelTank, motor);            
        }

        /// <summary>
        /// This would be accessed through some sort of UI letting the user pick a car and components
        /// </summary>
        /// <param name="car">The car the user picked</param>
        /// <param name="fuelTank">The fuel tank the user picked</param>
        /// <param name="motor">The motor the user picked</param>
        /// <returns>Player 2's configured car</returns>
        public ICar Player2Car(ICar car, IComponents fuelTank, IComponents motor)
        {
            //Assemble Player 2's car
            return MakeCars.AssembledCar(car, fuelTank, motor);
        }

        //lets get a track to race on
        /// <summary>
        /// This would be accessed through some sort of UI letting the user pick a track
        /// </summary>
        /// <param name="trackPickedByPlayer">The track the user picked</param>
        /// <returns>The instance of the track the user picked</returns>
        public Object TrackToRaceOn(string trackPickedByPlayer)
        {
            Tracks RaceOnThisTrack = new Tracks();

            if (trackPickedByPlayer == "Track 1")
            {
                return RaceOnThisTrack.RaceTrack1();
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// Performs a race
        /// </summary>
        /// <param name="player1">Player 1's configured car</param>
        /// <param name="player2">Player 2's configured car</param>
        /// <param name="track">The track to race on</param>
        /// <returns>The winner of the race</returns>
        public string RunRace(ICar player1, ICar player2, string track)
        {
            //get the track to race on
            Object Track = TrackToRaceOn(track);

            //keep track to see who wins
            bool player1Wins = false;
            bool player2Wins = false;

            player1Wins = player1.Drive(Track, player2);
            player2Wins = player2.Drive(Track, player1);

            if (player1Wins)
            {
                //some code to do something if player 1 wins the race
                string wins = "player1";
                return wins;
            }
            if (player2Wins)
            {
                //some code to do something if player 2 wins the race
                string wins = "player2";
                return wins;
            }
            if (player1Wins && player2Wins)
            {
                //some code to do something if there is a tie
                string wins = "tie";
                return wins;
            }
            else
            {
                return null;
            }
        }
    }

    class MyRacingCarProgram
    {
        //stuff to access the various components and perform the race
        //main part of the application
    }
}
Member Avatar for embooglement

That is more or less exactly how I would put together a racing game.

Also, it occurs to me you never answered whether or not you understood virtual functions and polymorphism. If you're still having trouble grasping interfaces, I'd suggest starting there.

embooglement,

No, I actually haven't researched or ever used virtual functions. You are the first person to bring them to my attention.

I think the main issue I have with the interfaces is determining what "class" was initialized when passing an instance of an interface class as a parameter.

Even in my race car example I was completely guessing when I put together public ICar AssembledCar(ICar selectedCar, IComponents fuelTank, IComponents motor) ...I'm still struggling to figure out how, if one method calls the AssembledCar() method and a ICar object is returned...how can the parent method find out "is this instance of the ICar object the red car or the blue car?" But I guess that's the whole point of using interfaces so that the methods don't HAVE to know. To get around that I embedded the name variable in each car and set it in the code...it's not a variable, that way I can just do a if/then/else or whatever referencing the object.name property.

I dunno...I'll figure it out I suppose. Right now I'm too scared to try implementing interfaces in my application...if I end up breaking tons of code I have no one to cry to but myself to fix it hehe...

Thanks a ton for your help! I really REALLY learned a lot the last few days.

I really do appreciate it. :)

Member Avatar for embooglement

Yeah, you really need to look into virtual functions and polymorphism, and maybe look into reference types vs. value types, if you really want to understand interfaces.

But to answer your original question: yes, interfaces are useful. :)

commented: so many good posts, all clear and informative :) +3

C# is a Complete Object Oriented Language
It fully implements the OOPs Concepts like Abstraction, Inheritance , Polymorphism
C# does not supports multiple inheritance means you can't inherit more than one class to create new class.
But this feature can be implemented by using interface.
Therefore interfaces are the way to implement functinality of multiple inheritance

Similar to the concept of delegates which are used in place of pointer for the purpose of indirect referecing.

Member Avatar for embooglement

@nareshgupta12: that's not entirely true. While you can inherit multiple interfaces, since interfaces don't actually provide any implementation, it doesn't really mimic multiple inheritance with classes. To do that you would use an inheritance chain with some kind of dummy class.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.