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.
csharp-basics/8-inheritance-and-abstract-...

308 lines
7.7 KiB
Markdown

---
marp: true
paginate: true
math: mathjax
theme: buutti
title: 8. Inheritance & Abstract Classes
---
# Inheritance & Abstract Classes
<!-- headingDivider: 5 -->
<!-- class: invert -->
## Overview
* Inheritance
* Abstract classes
* Enums
* OOP
## Inheritance
* Classes can be made to inherit functionality of some other class
* If class B inherits class A, all of the (public) functionality in class A is also available in class B
* A is called the *__base class__* (or parent class) and B is called the *__derived class__* (or child class)
* Use the `:` symbol to make a class inherit from another
### An inheritance example
<center>
| `class Animal` | `class Dog : Animal` | `class Cat : Animal` |
|:--------------:|:--------------------:|:--------------------:|
| `Eat()` | `Bark()` | `Meow()` |
| `Sleep()` | | |
</center>
<br>
<div class='columns111' markdown='1'>
<div markdown='1'>
* Animal can eat
* Animal can sleep
</div>
<div markdown='1'>
* Dog can eat
* Dog can sleep
* Dog can bark
</div>
<div markdown='1'>
* Cat can eat
* Cat can sleep
* Cat can meow
</div>
</div>
### Inheritance: An example implementation
<div class='columns' markdown='1'>
<div markdown='1'>
```csharp
class Animal
{
public void Eat()
{ Console.WriteLine("Eating..."); }
public void Sleep()
{ Console.WriteLine("Sleeping..."); }
}
class Cat : Animal
{
public void Meow()
{ Console.WriteLine("Meow!"); }
}
class Dog : Animal
{
public void Bark()
{ Console.WriteLine("Bark!"); }
}
```
</div>
<div markdown='1'>
```csharp
class Program
{
static void Main(string[] args)
{
Dog pluto = new Dog();
pluto.Eat(); // Outputs "Eating..."
pluto.Bark(); // Outputs "Bark!"
}
}
```
</div>
</div>
### Inheritance continued
* All the objects deriving from the same base class can be referenced with the base class name:
```csharp
Animal whiskersAnimal = new Cat();
Animal plutoAnimal = new Dog();
```
* However, only the methods of the base class are available for objects of the base class type:
```csharp
plutoAnimal.Eat(); // Outputs "Eating..."
plutoAnimal.Bark(); // Error
```
* An object of base class type can be *__cast__* into the child class type:
```csharp
Dog pluto = (Dog)plutoAnimal;
pluto.Bark(); // Outputs "Bark!"
```
## Abstract Classes
* In some cases you want the base class to be made [abstract](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/abstract)
* Objects of an abstract class ***cannot*** be instantiated
* For example, where would you need a generic `Animal` by itself?
* Make a class abstract with the `abstract` keyword:
```csharp
abstract class Animal
{
public void Eat() { Console.WriteLine("Eating..."); }
public void Sleep() { Console.WriteLine("Sleeping..."); }
}
class Program
{
static void Main(string[] args)
{
Animal animal = new Animal(); // This will throw an error
}
}
```
---
* Instead, the methods are accessible through a derived class:
```csharp
abstract class Animal
{
public void Eat() { Console.WriteLine("Eating..."); }
public void Sleep() { Console.WriteLine("Sleeping..."); }
}
class Pig : Animal
{
public void Squeal() { Console.WriteLine("Squeee!"); }
}
class Program
{
static void Main(string[] args)
{
Pig pig = new Pig();
pig.Sleep(); // Outputs "Sleeping..."
pig.Squeal(); // Outputs "Squeee!"
}
}
```
---
* If you know you only need the functionality of the abstract class, instantiate the new class as a type of abstract class:
```csharp
abstract class Animal
{
public void Eat() { Console.WriteLine("Eating..."); }
public void Sleep() { Console.WriteLine("Sleeping..."); }
}
class Pig : Animal
{
public void Squeal() { Console.WriteLine("Squeee!"); }
}
class Program
{
static void Main(string[] args)
{
Animal pig = new Pig();
pig.Sleep(); // Outputs "Sleeping..."
pig.Squeal(); // This will throw an error
}
}
```
## Exercise 1. Animal farm
<!--_class: "exercise invert" -->
1) Create the classes `Animal`, `Dog`, `Cat` and `Pig`. `Animal` is the same as before (strings `name` and `sound` and the `Greet()` method). `Dog`, `Cat` and `Pig` inherit `Animal`
2) Give `Dog`, `Cat` and `Pig` some fields and/or methods specific to that animal
3) Create a few instances of `Dog`, `Cat` and `Pig`, and add them to a list `allAnimals`
4) Loop through `allAnimals` with the `foreach` statement, and call the `Greet()` method of each animal
## Enums
* [Enum](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/enum) (short for enumeration) is a data type for holding a set of constant (immutable) names
* Enums can be useful when you have a given number of ***states*** that are predefined
* For example, weekdays
* Another example is an extension of boolean with three states `True`, `False` and `Maybe`
### Creating enums
* Create an `enum` type with the enum keyword:
```csharp
enum Season
{
Spring,
Summer,
Autumn,
Winter
}
```
* Then, create a new variable with the type `Season` and assign one of the enum type's values to it:
```csharp
Season currentSeason = Season.Spring;
```
### Enums: An example
<div class='columns12' markdown='1'>
<div markdown='1'>
In this example, an enum is used to keep track of the state of the program.
```csharp
enum ProgramState
{
Login,
Menu,
Exit
}
```
</div>
<div markdown='1'>
```csharp
static void Main(string[] args)
{
ProgramState currentState = ProgramState.Login;
while (true)
{
switch (currentState)
{
case ProgramState.Login:
// Switch current state to Menu after logging in
break;
case ProgramState.Menu:
// Switch current state to Exit if user exits
break;
case ProgramState.Exit:
// Exit the program with an exit message
break;
}
}
}
```
</div>
</div>
## Extra: Object Oriented Programming
<!-- _class: "extra invert" -->
* The instances that are created with the `new` keyword are ***objects***.
* This is literally what ***object orientation*** refers to: packing functionality into these reusable variables that are holding some data and can be passed around
* The key concepts of OOP are:
* Encapsulation
* Inheritance
* Abstraction
* Polymorphism
### Encapsulation
<!-- _class: "extra invert" -->
* Earlier we created classes that hold properties and methods that are only accessible elsewhere ***after*** instantiating an object of the class
* All the functionality is encapsulated inside of the class instead of lying around in the codebase
* All the functionality is made available **_only when it is needed_** by instantiating an object of the class
### Inheritance
<!-- _class: "extra invert" -->
* As shown earlier, inheritance allows you to write some functionality once, and then create separate classes which all share that same functionality
* This removes the need to rewrite the same code inside every class
### Abstraction
<!-- _class: "extra invert" -->
* When your class contains a lot of complicated functionality, it doesn't always make sense to reveal everything when the class is used
* Instead, reveal only the parts that the user (you, a workmate, etc) actually need, with abstraction
* Example: The user of a microwave doesn't have to know about the complicated circuitry inside of the microwave. Only the buttons are revealed
### Polymorphism
<!-- _class: "extra invert" -->
* This concept becomes more clear after we have covered interfaces in the next lecture
* Polymorphism refers to multiple classes having the same method but with different functionality
* This reduces the need for massive if-else and switch..case statements