Why do we use interface references to call methods of an object?

For example:

class Program : Iabc, Idef
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello interfaces");
        Program refProgram = new Program();
        Iabc refiabc = refProgram;
        refiabc.xyz();
        Idef refidef = refProgram;
        refidef.pqr();
        Console.ReadLine();
    }

    public void pqr()
    {
        Console.WriteLine("In pqr");
    }

    public void xyz()
    {
        Console.WriteLine("In xyz");
    }
}

The interface reference refiabc is pointing to the refProgram reference which is pointing to the Program object. refiabc then calls xyz()

Why do we do this (use interface references that point to a central reference that points to an object) instead of calling methods directly by making an instance of a class then calling its methods?

Example:

Why do this

Program refProgram = new Program();
        Iabc refiabc = refProgram;
        refiabc.xyz();

Instead of just doing this

Program refProgram = new Program();
refProgram.xyz();

Recommended Answers

All 4 Replies

I'm not really a C# programmer, so I could be a bit off.

An interface is a class that cannot be initialised into an object, but does provide information on how to handle classes that implement the interface. This idea is an extention onto polymorphism.

For example, you can write a function that accepts a "List" interface as a parameter. You can pass in any class that implements "List".

A reference is something that refers to another place in memory. For example, once you pass in a class to the function, the function is working with a reference to the list. (I should say that pointers are different in that you're allowed to directly access the address, but I don't think C# has pointers to worry about. Still, it's important to note if you move onto other languages.).

In your examples, you might as well go for the second one becasue of how trivial it is.

However, if your program involved both linked lists and array-based lists then you might want to work with just the interface "List" and only worry about what the actual type of the list is when you initialise it. This allows you to not worry about re-writing code for handeling linked lists and array-based lists.

How did you define Iabc and Idef?

Interface defined:

interface abc
{
  void xyz();
}

interface def
{
  void pqr();
}

Why do we use interface references to call methods of an object?

For the most part it's a poor man's polymorphism. An interface is a contract where the implementing class says "I promise to support at least the definition provided by the interface".

As long as a class implements the interface, that class can be accessed through an object of the interface:

interface IFoo;
class Bar : IFoo;
class Baz : IFoo;

static void Main(string[] args)
{
    IFoo obj1 = new Bar();
    IFoo obj2 = new Baz();
}

Of course, like your example, the above is nigh useless and just a complication over using the class directly. However, imagine instead a factory that gives you a different implementing class depending on its arguments:

static void Main(string[] args)
{
    var provider = GetMailProvider(server, port, user, pass, mailbox);

    ...
}

IMailProvider GetMailProvider(params object[] args)
{
    if (IsPop(args))
    {
        return new PopMailProvider(args);
    }
    else if (IsImap(args))
    {
        return new ImapMailProvider(args);
    }
    else if (IsEws(args))
    {
        return new EwsMailProvider(args);
    }
    else
    {
        throw new UnsupportedMailProvider(args);
    }
}

The calling code doesn't care which class it gets, because all of them support the same interface. provider is used the same way, so all three mail provider types are supported without extra logic in the client code. Further, the underlying classes may not be accessible to you, only the interface. In fact, this is precisely how I implemented my email library with support for multiple providers.

Returning back to the contract, it ensures that implementing classes must support the interface, and if it doesn't then usage of the class through an interface object will fail quickly and loudly. Another example from my own projects is a plugin. Imagine a simple plugin system where end users can write their own assembly that will hook into the functionality of the application through certain key events. Those assemblies will match an expected interface:

interface IApiHook
{
    public bool BeforeProcess(object thing);
    public void AfterProcess(object thing);
}

private IApiHook SetupApiHook()
{
    if (string.IsNullOrWhiteSpace(Settings.ApiHookQualifiedName))
    {
        return null; // No hook configured
    }

    var hookType = Type.GetType(Settings.ApiHookQualifiedName);

    if (hookType == null)
    {
        throw new HookNotFoundException("Selected API hook '" + Settings.ApiHookQualifiedName + "' could not be instantiated");
    }

    return (IApiHook)Activator.CreateInstance(hookType);
}

private void HookBeforeProcess(IApiHook apiHook)
{
    if (apiHook != null)
    {
        apiHook.BeforeProcess(currentThing);
    }
}

private void HookAfterProcess(IApiHook apiHook)
{
    if (apiHook != null)
    {
        apiHook.AfterProcess(currentThing);
    }
}

In this case it's not a matter of choosing not to use the class directly, it's a matter of being unable to do so in any convenient way. The interface makes this plugin approach viable. You don't control the details of the user-provided assembly, but you can enforce a public interface to glue everything together.

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.