Interfaces

Overview

  • Interfaces
  • Interfaces or Inheritance?

Interfaces

  • In addition to abstract classes, interfaces are a way to achieve abstraction to your program
  • Interfaces are classes that have no internal functionality
  • Interfaces describe the methods and properties that a class has to have when implementing the interface
    • Think of it as a contract: by implementing an interface, the class has to use all the methods and properties defined in the interface
  • As with abstract classes, interfaces cannot be instantiated directly
    • (It wouldn't make any sense as interfaces have no implementation)
  • Interfaces are way more commonly used than abstract classes

Creating an interface

  • Define an interface using the interface keyword instead of class:
    interface IUser
    {
      int Id { get; set; }
      string Name { get; set; }
      void GetUserStatistics();
    }
    
  • Interface names should begin with the capital letter I to more easily identify them as interfaces and not classes
  • Notice that interfaces can contain both properties and methods but not fields
  • Methods are declared without the method body (no implementation)
    • The methods are implemented on the classes that uses the interface

Implementing an interface

  • Implement an interface just like you would inherit a class:
    class User : IUser
    {
    
    }
    
  • The compiler will now throw a bunch of errors saying that the User class does not implement the properties and methods defined in the interface
  • Let's fix that by defining those next
class User : IUser
{
  public int Id { get; set; }
  public string Name { get; set; }
  public void GetUserStatistics()
  {
    // Some code here
  }
}
  • The interface is now fully implemented and the compiler is happy
  • The interface does not dictate how the methods are implemented, those just need to be implemented
  • Note: To quickly implement the interface, click the IUser interface name and click 💡 > Implement interface.

Implementing multiple interfaces

  • Unlike with inheritance, classes can implement multiple interfaces
    • In contrast, classes can only inherit from one base class
  • This is done by separating the interfaces with a comma:
    class Rock : IPickable, IThrowable, ICrushable
    {
    // Code that implements IPickable, IThrowable and ICrushable
    }
    

Why use interfaces?

  • Interfaces allow common functionality among classes that are otherwise unrelated to each other
  • In those cases, inheriting from some shared base class wouldn't make sense
  • Consider the following example:
    public void DeleteData(IDeletable data)
    {
      data.Delete();
    }
    
  • The above method accepts any type of object that implements IDeletable, regardless of other functionality

Interface or Inheritance?

Example 1

class Dog class Human class Bear
Eat() Eat() Eat()
Sleep() Sleep() Sleep()
WagTail() Contemplate() Hibernate()
  • All classes could inherit from a base class Animal, which has methods Eat() and Sleep()
  • The question is, should the base class be abstract?
    • Depends on your program: do you ever need an object that can only Eat() and Sleep()?

Example 2

class Tree class Human class Car
Grow() Grow() Explode()
Photosynthesize() Move() Move()
  • It wouldn't make sense to use inheritance here, since there is no functionality that is shared between all classes
  • Instead you could make two interfaces: IGrowable and IMovable

Interfaces: An example

  • Let's make a program that has two lists: one for all objects that can move (IMovable) and one for all objects that can be carried (ICarryable)
  • Finally, every movable object is moved and carryable object is carried
interface IMovable
{
  void Move();
}
interface ICarryable
{
  void Carry();
}
class Elephant : IMovable
{
  public void Move()
  {
    Console.WriteLine("The elephant is moving'");
  }
}
class Cat : IMovable, ICarryable
{
  public void Move()
  {
    Console.WriteLine("The cat is moving'");
  }
  public void Carry()
  {
    Console.WriteLine("You are carrying the cat");
  }
}
class Rock : ICarryable
{
  public void Carry()
  {
    Console.WriteLine("You are carrying the rock");
  }
}
class Program
{
  static void Main(string[] args)
  {
    Elephant elephant = new Elephant();
    Cat cat = new Cat();
    Rock rock = new Rock();

    List<IMovable> movables =
      new List<IMovable>{ elephant, cat };
    List<ICarryable> carryables =
      new List<ICarryable>{ cat, rock };

    foreach (IMovable movable in movables)
      movable.Move();

    foreach (ICarryable carryable in carryables)
      carryable.Carry();
  }
}

Exercise 1: A web of relations

Create a console application that has an interface IInfo and two classes Product and Category that both implement IInfo.

  1. Inside IInfo, declare a property InfoText and a method PrintInfo
  2. Implement both the property and method in Product and Category
  3. Initialize a couple of products and categories, with info texts of your choice
  4. Create a list of type IInfo, and add the products and categories to it
  5. Create a main loop, where each time the user presses enter, all the info texts inside the list are printed

Exercise 2: The IComparable Interface

Create a program that sorts a list of shapes by area, using the IComparable interface which is used by the List.Sort() method to know whether the elements should come before or after each other in the list.

  1. Start by creating 4 classes: Shape, Square, Triangle, and Circle. Square, Triangle and Circle inherit from Shape, which implements the IComparable<Shape> interface.
  2. Shape has a public property double Area. Square, Triangle and Circle have to have constructors to calculate the area: Square and Triangle with length and height, and Circle with radius.
  1. The CompareTo(Shape? other) method should return 1 if the area is greater than what is being compared with (Shape other), 0 if the areas are equal, and -1 if the area is smaller.
  2. Try out your solution by creating a couple of squares, triangles and circles in a list of shapes, and sorting the list with the .Sort() method.
  3. Print the areas in the sorted array with a foreach loop. They should be printed in an increasing order.