---
marp: true
paginate: true
math: mathjax
theme: buutti
title: 9. Interfaces
---
# Interfaces

<!-- headingDivider: 5 -->
<!-- class: invert -->

## 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](8-inheritance-and-abstract-classes.md#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:
  ```csharp
  interface IUser
  {
    int Id { get; set; }
    string Name { get; set; }
    void GetUserStatistics();
  }
  ```
* [Interface names should begin](https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces) 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:
  ```csharp
  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

---

```csharp
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:
  ```csharp
  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:
  ```csharp
  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

<center>

| `class Dog` | `class Human`   | `class Bear`  |
|:------------|:----------------|:--------------|
| `Eat()`     | `Eat()`         | `Eat()`       |
| `Sleep()`   | `Sleep()`       | `Sleep()`     |
| `WagTail()` | `Contemplate()` | `Hibernate()` |

</center>

* 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

<center>

| `class Tree`        | `class Human` | `class Car` |
|:--------------------|:--------------|:------------|
| `Grow()`            | `Grow()`      | `Explode()`    |
| `Photosynthesize()` | `Move()`      | `Move()` |

</center>

* 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

---

<div class='columns12' markdown='1'>
<div markdown='1'>

```csharp
interface IMovable
{
  void Move();
}
interface ICarryable
{
  void Carry();
}
```

</div>
<div markdown='1'>

```csharp
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");
  }
}
```

</div>
</div>

---

<div class='columns21' markdown='1'>
<div markdown='1'>

```csharp
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();
  }
}
```

</div>
<div markdown='1'>

![](imgs/9%20Interfaces_1.png)

</div>
</div>



## Exercise 1: A web of relations
<!--_class: "exercise invert" -->

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
<!--_class: "exercise invert" -->

Create a program that sorts a list of shapes by area, using the  [IComparable](https://docs.microsoft.com/en-us/dotnet/api/system.collections.icomparer?view=netcore-3.1) 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`.

---
<!--_class: "exercise invert" -->

3) `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.
4) 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.
5) Print the areas in the sorted array with a `foreach` loop. They should be printed in an increasing order.

