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.
308 lines
7.7 KiB
Markdown
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
|
|
|