You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

271 lines
6.2 KiB
Markdown

# Interfaces
![](imgs/9%20Interfaces_0.png)
---
# 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 that are 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 I letter 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 now
# Implementing an Interface (continued)
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 do not dictate _how_ the methods are implemented, those just need to be implemented.
To quickly implement the interface, click the IUser interface name and click the light bulb -> 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?
| class Dog |
| :-: |
| -Eat()-Sleep()-WagTail() |
| class Human |
| :-: |
| -Eat()-Sleep()-Contemplate() |
| class Bear |
| :-: |
| -Eat()-Sleep()-Hibernate() |
All classes could inherit from a base class Animal, which has methods Eat() and Sleep()
Should the base class be abstract? Depends on your program: do you ever need an object that can only Eat() and Sleep()?
| class Tree |
| :-: |
| -Grow()-Photosynthesize() |
| class Human |
| :-: |
| -Grow()-Move() |
| class Car |
| :-: |
| -Move()-Explode() |
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 - 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();
}
}
![](imgs/9%20Interfaces_1.png)
# Exercise 1: A Web of Relations
Create a console application that has an interface IInfo, and two classes Product and Category, which both implement IInfo.
Inside IInfo, declare a property InfoText and a method PrintInfo
Implement the property and method in Product and Category
Initialize a couple of products and categories, with info texts of your choice
Create a list of type IInfo, and add the products and categories to it
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](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.
Start by creating 4 classes: __Shape__ , __Square__ , __Triangle__ and __Circle__ . Square, Triangle and Circle inherit from Shape. Shape implements the __IComparable\<Shape>__ __ __ interface.
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.
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.
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. Print the areas in the sorted array with a foreach loop. They should be printed in an increasing order.