Implementing Interfaces


To implement an interface, a class derives from the interface and supplies implementations of all its components. The syntax for doing this is shown below.

class class-name : interface-name
{
 // ... class body
}

All components of the interface must be implemented, an interface cannot be partially implemented. A class can implement multiple interfaces. The syntax for doing this is to supply a comma-separated list of interface names. A class can also inherit from a base class and implement one or more interfaces. In this case, the name of the base class must come first in the comma-separated list.

The methods that implement an interface must be declared as public. This is because methods within an interface are implicitly declared as public, therefore their implementations must also be public. The return type and signature of the implementing method must match the return type and signature of the original declaration of the method within the interface.

Below is an example that implements an interface called ISequence.

// Interface1 - Implementing an Interface

using System;

public interface ISequence
{
    uint Next();         // Return the next number
    void Reset();        // Reset to start
    void Start(uint s);  // Set starting point
}

class Seconds : ISequence
{
    uint start;
    uint current;

    public Seconds()
    {
        start = current = 0;
    }

    public uint Next()
    {
        current += 2;
        return current;
    }

    public void Reset()
    {
        current = start;
    }

    public void Start(uint s)
    {
        current = start = s;
    }
}


class Program
{
    static void Main()
    {
        Seconds seconds = new Seconds();
        
        for (uint i = 0; i < 3; i++)
            Console.WriteLine("Next Value: {0}", seconds.Next());

        Console.WriteLine("Resetting");
        seconds.Reset();

        for (uint i = 0; i < 3; i++)
            Console.WriteLine("Next Value: {0}", seconds.Next());

        Console.WriteLine("Starting at 100");
        seconds.Start(100);

        for (uint i = 0; i < 3; i++)
            Console.WriteLine("Next Value: {0}", seconds.Next());
    }
}

The output of the program is shown below.

Next Value: 2
Next Value: 4
Next Value: 6
Resetting
Next Value: 2
Next Value: 4
Next Value: 6
Starting at 100
Next Value: 102
Next Value: 104
Next Value: 106

A radically different implementation of the ISequence interface is a program that generates a series of prime numbers. Such a program is shown below.

// Interface2 - Implementing an Interface - Primes

using System;

public interface ISequence
{
    uint Next();         // Return the next number
    void Reset();        // Reset to start
    void Start(uint s);  // Set starting point
}

class Primes : ISequence
{
    uint start;
    uint current;

    public Primes()
    {
        start = current = 1;
    }

    public uint Next()
    {
        do
        {
            current++;
        } while (!IsPrime());

        return current;
    }

    public void Reset()
    {
        current = start;
    }

    public void Start(uint s)
    {
        current = start = s;
    }

    bool IsPrime()
    {
        if (current < 2) return false;

        bool is_prime = true;

        uint j = 2;
        uint limit = (uint)Math.Sqrt(current);

        while (j <= limit)
        {
            if (current % j == 0) {is_prime = false; break;}
            j++;
        }

        return is_prime;
    }
}

class Program
{
    static void Main()
    {
        Primes p = new Primes();

        for (uint i = 0; i < 3; i++)
            Console.WriteLine("Next Prime: {0}", p.Next());

        Console.WriteLine("Resetting");
        p.Reset();

        for (uint i = 0; i < 3; i++)
            Console.WriteLine("Next Prime: {0}", p.Next());

        Console.WriteLine("Starting at 100");
        p.Start(100);

        for (uint i = 0; i < 3; i++)
            Console.WriteLine("Next Prime: {0}", p.Next());
    }
}

The output of this new program is shown below.

Next Prime: 2
Next Prime: 3
Next Prime: 5
Resetting
Next Prime: 2
Next Prime: 3
Next Prime: 5
Starting at 100
Next Prime: 101
Next Prime: 103
Next Prime: 107

The fact that the interface ISequence can be used to generate numbers in increments of two or as a prime number generator illustrates the point that interfaces are usually designed to be very general in their meaning. Classes may be written that manipulate sequences (through ISequence) and these class require no knowledge of the specific implementation of the sequences.