finish lectures 8-10

- fix code snippets
- update readme
main
borb 2 weeks ago
parent 76b49a6af8
commit 24ec8f9349

@ -68,10 +68,10 @@
}, },
"exercise slide" : { "exercise slide" : {
"scope": "markdown", "scope": "markdown",
"prefix": "\"exercise invert\"", "prefix": "exercise",
"body": [ "body": [
"## Exercise $0.", "## Exercise $0.",
"<!--_class: exercise -->", "<!--_class: \"exercise invert\" -->",
], ],
"description": "Exercise slide colors" "description": "Exercise slide colors"
}, },

File diff suppressed because one or more lines are too long

@ -1,233 +1,198 @@
# Static Members, Methods and Classes ---
marp: true
![](imgs/10%20Static%20Members%2C%20Methods%20and%20Classes_0.png) paginate: true
math: mathjax
theme: buutti
title: 10. Static Members, Methods and Classes
--- ---
# Static Members # Static Members, Methods and Classes
So far, we have used __non-static__ fields in our classes <!-- headingDivider: 5 -->
<!-- class: invert -->
This means, that each instance of the class holds its own version of the field, and changing the value of it only affects that instance: ## Static Members
class MyAwesomeClass ### Non-static members
* So far, we have used *__non-static__* fields in our classes
* Meaning that each instance of the class holds its own version of the field, and changing the value of it only affects that instance:
```csharp
class MyAwesomeClass
{ {
public int MyProperty { get; set; } public int MyProperty { get; set; }
} }
class Program class Program
{ {
static void Main(string[] args) static void Main(string[] args)
{ {
MyAwesomeClass instance1 = new MyAwesomeClass(); MyAwesomeClass instance1 = new MyAwesomeClass();
MyAwesomeClass instance2 = new MyAwesomeClass(); MyAwesomeClass instance2 = new MyAwesomeClass();
instance1.MyProperty = 100; instance1.MyProperty = 100;
instance2.MyProperty = 200; // instance1.MyProperty is still 100 instance2.MyProperty = 200; // instance1.MyProperty is still 100
} }
} }
```
# Static Members (continued) ---
Likewise, non-static class methods _have to _ be called through an instance:
* Likewise, non-static class methods **_have to_** be called through an instance:
```csharp
class MyAwesomeClass class MyAwesomeClass
{ {
public void PrintText(string text)
public void PrintText(string text) { Console.WriteLine(text); } {
Console.WriteLine(text);
}
} }
class Program class Program
{ {
static void Main(string[] args) static void Main(string[] args)
{ {
MyAwesomeClass instance = new MyAwesomeClass(); MyAwesomeClass instance = new MyAwesomeClass();
instance.PrintText("Hello World"); // Outputs "Hello World" instance.PrintText("Hello World"); // Outputs "Hello World"
MyAwesomeClass.PrintText("Hello World"); // Results in an error MyAwesomeClass.PrintText("Hello World"); // Results in an error
} }
} }
```
<div class='centered'>
![](imgs/10%20Static%20Members%2C%20Methods%20and%20Classes_1.png) ![w:500px](imgs/10%20Static%20Members%2C%20Methods%20and%20Classes_1.png)
__Static fields are shared between all instances of a class__ </div>
Let's declare "MyProperty" property with the __static __ keyword. Now it can be referenced through the class type name, but not through the instance, as shown below: ### Static members
* Let's declare a property `MyProperty` with the `static` keyword
* It can be referenced *through the class*, but ***not*** through the instance:
```csharp
class MyAwesomeClass class MyAwesomeClass
{ {
public static int MyProperty { get; set; } = 100; public static int MyProperty { get; set; } = 100;
} }
class Program class Program
{ {
static void Main(string[] args) static void Main(string[] args)
{ {
MyAwesomeClass instance = new MyAwesomeClass(); MyAwesomeClass instance = new MyAwesomeClass();
Console.WriteLine(MyAwesomeClass.MyProperty); // Outputs "100" Console.WriteLine(MyAwesomeClass.MyProperty); // Outputs "100"
Console.WriteLine(instance.MyProperty); // Results in an error Console.WriteLine(instance.MyProperty); // Results in an error
} }
} }
```
![](imgs/10%20Static%20Members%2C%20Methods%20and%20Classes_2.png) <div class='centered'>
# Static Members - Example ![w:600px](imgs/10%20Static%20Members%2C%20Methods%20and%20Classes_2.png)
In this example, a static field is used for keeping count on how many times the class has been instantiated: </div>
class Person
{ ### Static members: An example
* In this example, a static field is used for keeping count on how many times the class has been instantiated:
```csharp
class Person
{
public static int totalPersons = 0; public static int totalPersons = 0;
private string name; private string name;
public Person(string personName) // Person Constructor public Person(string personName) // Person Constructor
{ {
name = personName; name = personName;
++totalPersons; ++totalPersons;
} }
public void PrintInfo() public void PrintInfo()
{ {
Console.WriteLine("This person is called " + name + "."); Console.WriteLine("This person is called " + name + ".");
Console.WriteLine("There are " + totalPersons + " persons total."); Console.WriteLine("There are " + totalPersons + " persons total.");
} }
} }
```
# Static Members - Example (continued) ---
Now let's instantiate a couple of persons and print their info:
class Program * Now let's instantiate a couple of persons and print their info:
{ <div class='columns21' markdown='1'>
<div markdown='1'>
```csharp
class Program
{
static void Main(string[] args) static void Main(string[] args)
{ {
Person steve = new Person("Steve"); Person steve = new Person("Steve");
Person wendy = new Person("Wendy"); Person wendy = new Person("Wendy");
steve.PrintInfo(); steve.PrintInfo();
wendy.PrintInfo(); wendy.PrintInfo();
} }
} }
```
![](imgs/10%20Static%20Members%2C%20Methods%20and%20Classes_3.png) </div>
<div markdown='1'>
# Static Methods ![w:400px](imgs/10%20Static%20Members%2C%20Methods%20and%20Classes_3.png)
Methods can also be static </div>
</div>
What happens when you try to call a non-static method from a static method? ## Static methods
* Methods can also be static
* What happens when you try to call a non-static method from a static method?
```csharp
class Program class Program
{ {
void PrintHelloName(string name) void PrintHelloName(string name)
{ {
Console.WriteLine("Hello, " + name); Console.WriteLine("Hello, " + name);
} }
static void Main(string[] args) static void Main(string[] args)
{ {
PrintHelloName(); // Will throw an error PrintHelloName(); // Will throw an error
} }
} }
```
![](imgs/10%20Static%20Members%2C%20Methods%20and%20Classes_4.png) <div class='centered'>
---
This is why until this point all example methods have been inside of the main function
# Static Classes
* Classes can also be made static ![w:800px](imgs/10%20Static%20Members%2C%20Methods%20and%20Classes_4.png)
* Static classes cannot be instantiated
* All members of a static class also have to be static
* static class Styling
* {
* public static string fontFamily = "Verdana";
* public static float fontSize = 12.5f;
* }
* class Program
* {
* static void Main(string[] args)
* {
* Console.WriteLine
* ("Using font " + Styling.fontFamily + " " + Styling.fontSize + "px");
* // Outputs "Using font Verdana 12.5px"
* Styling = new Styling(); // Results in an error
* }
* }
# Exercise 1 </div>
Create a class Message which has two __static __ properties int TotalMessages and string LastMessage, and a __non-static __ property string MessageText. ## Static classes
Add a constructor which takes a string message as a parameter, increases TotalMessages by one and sets the value of LastMessage to message which is the parameter * Whole classes can also be static
* Static classes cannot be instantiated, and all its members have to be static as well
```csharp
static class Styling
{
public static string fontFamily = "Verdana";
public static float fontSize = 12.5f;
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine
("Using font " + Styling.fontFamily + " " + Styling.fontSize + "px");
// Outputs "Using font Verdana 12.5px"
Styling = new Styling(); // Results in an error
}
}
```
Create a main loop which keeps asking the user for a new message. A new Message instance is then created with the user input message as an argument: ## Exercise 1
<!--_class: "exercise invert" -->
* Create a class `Message` that has two `static` properties `int TotalMessages` and `string LastMessage`, and a *__non-static__* property `string MessageText`.
* Add a constructor that takes a `string message` as a parameter, increases `TotalMessages` by one and sets the value of `LastMessage` to `message`.
* Create a main loop that keeps asking the user for a new message. A new `Message` instance is then created with the user input message as an argument:
```csharp
Message newMessage = new Message(message); Message newMessage = new Message(message);
```
newMessage is then added to a list of messages, allMessages * `newMessage` is then added to a list `allMessages`.
* Finally, the static values `Message.TotalMessages` and `Message.LastMessage` are printed.
Finally the static values Message.TotalMessages and Message.LastMessage are printed

File diff suppressed because one or more lines are too long

@ -1,302 +1,307 @@
# Inheritance & Abstract Classes ---
marp: true
![](imgs/8%20Inheritance%20%26%20Abstract%20Classes_0.png) paginate: true
math: mathjax
theme: buutti
title: 8. Inheritance & Abstract Classes
--- ---
# Overview # Inheritance & Abstract Classes
Inheritance
Abstract Classes
Enums <!-- headingDivider: 5 -->
<!-- class: invert -->
# Inheritance ## Overview
Classes can be made to inherit functionality of some other class * Inheritance
* Abstract classes
* Enums
* OOP
If class B inherits class A, all of the (public) functionality in class A is also available in class B ## Inheritance
A is called the __base class__ (or parent class) and B is called the __derived class __ (or child class) * 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
Use the " __:"__ symbol to make a class inherit from another ### An inheritance example
Try to understand the following example: <center>
| class Animal | | `class Animal` | `class Dog : Animal` | `class Cat : Animal` |
| :-: | |:--------------:|:--------------------:|:--------------------:|
| -Eat()-Sleep() | | `Eat()` | `Bark()` | `Meow()` |
| `Sleep()` | | |
| class Dog : Animal | </center>
| :-: |
| -Bark() |
| class Cat : Animal | <br>
| :-: |
| -Meow() |
Animal can eat <div class='columns111' markdown='1'>
<div markdown='1'>
Animal can sleep * Animal can eat
* Animal can sleep
Dog can eat </div>
<div markdown='1'>
Dog can sleep * Dog can eat
* Dog can sleep
* Dog can bark
Dog can bark </div>
<div markdown='1'>
Cat can eat * Cat can eat
* Cat can sleep
* Cat can meow
Cat can sleep </div>
</div>
Cat can meow ### Inheritance: An example implementation
# Inheritance - Example <div class='columns' markdown='1'>
<div markdown='1'>
```csharp
class Animal class Animal
{ {
public void Eat()
public void Eat() { Console.WriteLine("Eating..."); } { Console.WriteLine("Eating..."); }
public void Sleep()
public void Sleep() { Console.WriteLine("Sleeping..."); } { Console.WriteLine("Sleeping..."); }
} }
class Cat : Animal class Cat : Animal
{ {
public void Meow()
public void Meow() { Console.WriteLine("Meow!"); } { Console.WriteLine("Meow!"); }
} }
class Dog : Animal class Dog : Animal
{ {
public void Bark()
public void Bark() { Console.WriteLine("Bark!"); } { Console.WriteLine("Bark!"); }
} }
```
class Program </div>
<div markdown='1'>
```csharp
class Program
{ {
static void Main(string[] args) static void Main(string[] args)
{ {
Dog pluto = new Dog(); Dog pluto = new Dog();
pluto.Eat(); // Outputs "Eating..." pluto.Eat(); // Outputs "Eating..."
pluto.Bark(); // Outputs "Bark!" pluto.Bark(); // Outputs "Bark!"
} }
} }
```
# Inheritance </div>
</div>
All the objects deriving from the same base class can be referenced with the base class name: ### 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 whiskersAnimal = new Cat();
Animal plutoAnimal = new Dog(); Animal plutoAnimal = new Dog();
```
However, only the methods of the base class are available for objects of the base class type: * However, only the methods of the base class are available for objects of the base class type:
```csharp
plutoAnimal.Eat(); // Outputs "Eating..." plutoAnimal.Eat(); // Outputs "Eating..."
plutoAnimal.Bark(); // Error plutoAnimal.Bark(); // Error
```
An object of base class type can be __casted __ into the child class type: * An object of base class type can be *__cast__* into the child class type:
```csharp
Dog pluto = (Dog)plutoAnimal; Dog pluto = (Dog)plutoAnimal;
pluto.Bark(); // Outputs "Bark!" pluto.Bark(); // Outputs "Bark!"
```
# Abstract Classes ## Abstract Classes
* In some cases you want the base class to be made __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:
* 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:
* 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 abstract class Animal
{ {
public void Eat() { Console.WriteLine("Eating..."); } public void Eat() { Console.WriteLine("Eating..."); }
public void Sleep() { Console.WriteLine("Sleeping..."); } public void Sleep() { Console.WriteLine("Sleeping..."); }
} }
class Program
{
static void Main(string[] args)
{
Animal animal = new Animal(); // This will throw an error
}
}
```
class Pig : Animal ---
* 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!"); } public void Squeal() { Console.WriteLine("Squeee!"); }
} }
class Program class Program
{ {
static void Main(string[] args) static void Main(string[] args)
{ {
Pig pig = new Pig(); Pig pig = new Pig();
pig.Sleep(); // Outputs "Sleeping..." pig.Sleep(); // Outputs "Sleeping..."
pig.Squeal(); // Outputs "Squeee!" 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:
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 }}
--- ---
This is called abstraction, which is one of the key concepts of OOP * If you know you only need the functionality of the abstract class, instantiate the new class as a type of abstract class:
```csharp
# Exercise 1 abstract class Animal
{
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 public void Eat() { Console.WriteLine("Eating..."); }
public void Sleep() { Console.WriteLine("Sleeping..."); }
Give Dog, Cat and Pig some fields and/or methods specific to that animal }
class Pig : Animal
Create a few instances of Dog, Cat and Pig classes, and add them to a new list of Animals, named "allAnimals" {
public void Squeal() { Console.WriteLine("Squeee!"); }
Loop through allAnimals with the foreach statement, and call the Greet() method of each animal }
class Program
{
static void Main(string[] args)
{
Animal pig = new Pig();
pig.Sleep(); // Outputs "Sleeping..."
pig.Squeal(); // This will throw an error
}
}
```
# Enum ## Exercise 1. Animal farm
<!--_class: "exercise invert" -->
__Enum __ (short for enumeration) is a data type for holding a set of constant (immutable) names 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 can be useful when you have a number of items or states that are predefined, for example, weekdays ## Enums
Create the enum type with the enum keyword: * [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`
enum Weekday{ Monday, Tuesday, Wednesday, Thursday, Friday, Saturday} ### Creating enums
New instances of the enum can only be assigned one of the values within: * 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;
```
Weekday currentDay = Weekday.Monday; ### Enums: An example
# Enum - Example <div class='columns12' markdown='1'>
<div markdown='1'>
In this example, enum is used to keep track of the state of the program: In this example, an enum is used to keep track of the state of the program.
```csharp
enum ProgramState enum ProgramState
{ {
Login, Login,
Menu, Menu,
Exit Exit
} }
```
static void Main(string[] args) </div>
<div markdown='1'>
```csharp
static void Main(string[] args)
{ {
ProgramState currentState = ProgramState.Login; ProgramState currentState = ProgramState.Login;
while (true) while (true)
{ {
switch (currentState) switch (currentState)
{ {
case ProgramState.Login: case ProgramState.Login:
// Switch current state to Menu after logging in // Switch current state to Menu after logging in
break; break;
case ProgramState.Menu: case ProgramState.Menu:
// Switch current state to Exit if user exits // Switch current state to Exit if user exits
break; break;
case ProgramState.Exit: case ProgramState.Exit:
// Exit the program with an exit message // Exit the program with an exit message
break; break;
} }
} }
} }
```
</div>
</div>
# Going Further: Object Oriented Programming ## 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 instances that are created with the `new` keyword are ***objects***.
* The key concepts of OOP are * 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 * Encapsulation
* Inheritance * Inheritance
* Abstraction, and * Abstraction
* Polymorphism * Polymorphism
# OOP: Encapsulation ### Encapsulation
<!-- _class: "extra invert" -->
Earlier we created classes which hold properties and methods, which 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 made available _only when it is needed _ by instantiating an object of the class
# OOP: Inheritance
As shown in the lecture slides, inheritance allows you to write some functionality once, and then create separate classes which all share that same functionality
This removes the need to write the same code inside every class
# OOP: Abstraction
When your class contains a lot of complicated functionality, it doesn't always make sense to reveal everything when the class is used * 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
Instead, reveal only the parts that the user (you, a workmate, etc) actually need, with abstraction ### Inheritance
<!-- _class: "extra invert" -->
Parable: The user of a microwave doesn't have to know about the complicated circuitry inside of the microwave. Only the buttons are revealed * 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
# OOP: Polymorphism ### Abstraction
<!-- _class: "extra invert" -->
This concept becomes more clear after we have covered interfaces * 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 refers to multiple classes having the same method but with different functionality ### Polymorphism
<!-- _class: "extra invert" -->
This reduces the need for massive if-else and switch..case statements * 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

File diff suppressed because one or more lines are too long

@ -1,270 +1,248 @@
# Interfaces
![](imgs/9%20Interfaces_0.png)
--- ---
marp: true
paginate: true
math: mathjax
theme: buutti
title: 9. Interfaces
---
# Interfaces
# Overview <!-- headingDivider: 5 -->
<!-- class: invert -->
Interfaces ## Overview
Interfaces or Inheritance? * Interfaces
* Interfaces or Inheritance?
# Interfaces ## Interfaces
* In addition to abstract classes, __interfaces __ are a way to achieve abstraction to your program * In addition to abstract classes, *__interfaces__* are a way to achieve abstraction to your program
* Interfaces are classes that have __no internal functionality__ * Interfaces are classes that have *__no internal functionality__*
* Interfaces describe the methods and properties that a class has to have when implementing the interface * 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 * 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 * 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 * (It wouldn't make any sense as interfaces have no implementation)
* Interfaces are way more commonly used than abstract classes * Interfaces are way more commonly used than abstract classes
# Creating an Interface ### Creating an interface
* Define an interface using the interface keyword instead of class: * Define an interface using the interface keyword instead of class:
* interface IUser ```csharp
* { interface IUser
* int Id { get; set; } {
* string Name { get; set; } int Id { get; set; }
* void GetUserStatistics(); 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 ```
* [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) * Methods are declared without the method body (no implementation)
* The methods are implemented on the classes that uses the interface * The methods are implemented on the classes that uses the interface
# Implementing an Interface ### Implementing an interface
Implement an interface just like you would inherit a class:
* Implement an interface just like you would inherit a class:
```csharp
class User : IUser 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
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)
```csharp
class User : IUser class User : IUser
{ {
public int Id { get; set; } public int Id { get; set; }
public string Name { get; set; } public string Name { get; set; }
public void GetUserStatistics() public void GetUserStatistics()
{ {
// Some code here // 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_.
The interface is now fully implemented and the compiler is happy ### Implementing multiple interfaces
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 * Unlike with inheritance, classes can implement multiple interfaces
* In contrast, classes can only inherit from one base class * In contrast, classes can only inherit from one base class
* This is done by separating the interfaces with a comma: * This is done by separating the interfaces with a comma:
* class Rock : IPickable, IThrowable, ICrushable ```csharp
* { class Rock : IPickable, IThrowable, ICrushable
* // Code that implements IPickable, IThrowable and 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: ### 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) public void DeleteData(IDeletable data)
{ {
data.Delete(); data.Delete();
} }
```
* The above method accepts **_any_** type of object that implements `IDeletable`, regardless of other functionality
The above method accepts _any _ type of object that implements IDeletable, regardless of other functionality ## Interface or Inheritance?
# Interface or Inheritance? ### Example 1
| class Dog | <center>
| :-: |
| -Eat()-Sleep()-WagTail() |
| class Human | | `class Dog` | `class Human` | `class Bear` |
| :-: | |:------------|:----------------|:--------------|
| -Eat()-Sleep()-Contemplate() | | `Eat()` | `Eat()` | `Eat()` |
| `Sleep()` | `Sleep()` | `Sleep()` |
| `WagTail()` | `Contemplate()` | `Hibernate()` |
| class Bear | </center>
| :-: |
| -Eat()-Sleep()-Hibernate() |
All classes could inherit from a base class Animal, which has methods Eat() and Sleep() * 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()`?
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 | <center>
| :-: |
| -Grow()-Photosynthesize() |
| class Human | | `class Tree` | `class Human` | `class Car` |
| :-: | |:--------------------|:--------------|:------------|
| -Grow()-Move() | | `Grow()` | `Grow()` | `Explode()` |
| `Photosynthesize()` | `Move()` | `Move()` |
| class Car | </center>
| :-: |
| -Move()-Explode() |
It wouldn't make sense to use inheritance here, since there is no functionality that is shared between all classes * 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`
Instead you could make two interfaces: IGrowable and IMovable ## Interfaces: An example
# 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
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 interface IMovable
{ {
void Move(); void Move();
} }
interface ICarryable interface ICarryable
{ {
void Carry(); void Carry();
} }
```
class Elephant : IMovable </div>
<div markdown='1'>
```csharp
class Elephant : IMovable
{ {
public void Move() public void Move()
{ {
Console.WriteLine("The elephant is moving'"); Console.WriteLine("The elephant is moving'");
} }
} }
class Cat : IMovable, ICarryable class Cat : IMovable, ICarryable
{ {
public void Move() public void Move()
{ {
Console.WriteLine("The cat is moving'"); Console.WriteLine("The cat is moving'");
} }
public void Carry() public void Carry()
{ {
Console.WriteLine("You are carrying the cat"); Console.WriteLine("You are carrying the cat");
} }
} }
class Rock : ICarryable class Rock : ICarryable
{ {
public void Carry() public void Carry()
{ {
Console.WriteLine("You are carrying the rock"); Console.WriteLine("You are carrying the rock");
} }
} }
```
class Program </div>
</div>
{ ---
static void Main(string[] args) <div class='columns21' markdown='1'>
<div markdown='1'>
```csharp
class Program
{
static void Main(string[] args)
{ {
Elephant elephant = new Elephant(); Elephant elephant = new Elephant();
Cat cat = new Cat(); Cat cat = new Cat();
Rock rock = new Rock(); Rock rock = new Rock();
List<IMovable> movables = new List<IMovable>{ elephant, cat }; List<IMovable> movables =
new List<IMovable>{ elephant, cat };
List<ICarryable> carryables = new List<ICarryable>{ cat, rock }; List<ICarryable> carryables =
new List<ICarryable>{ cat, rock };
foreach (IMovable movable in movables) foreach (IMovable movable in movables)
movable.Move(); movable.Move();
foreach (ICarryable carryable in carryables) foreach (ICarryable carryable in carryables)
carryable.Carry(); carryable.Carry();
} }
} }
```
![](imgs/9%20Interfaces_1.png) </div>
<div markdown='1'>
# 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. ![](imgs/9%20Interfaces_1.png)
Inside IInfo, declare a property InfoText and a method PrintInfo </div>
</div>
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 ## Exercise 1: A web of relations
<!--_class: "exercise invert" -->
Create a main loop, where each time the user presses enter, all the info texts inside the list are printed Create a console application that has an interface `IInfo` and two classes `Product` and `Category` that both implement `IInfo`.
# Exercise 2: The IComparable Interface 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
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. ## Exercise 2: The `IComparable` Interface
<!--_class: "exercise invert" -->
Start by creating 4 classes: __Shape__ , __Square__ , __Triangle__ and __Circle__ . Square, Triangle and Circle inherit from Shape. Shape implements the __IComparable\<Shape>__ __ __ 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.
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) 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`.
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. ---
<!--_class: "exercise invert" -->
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. 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.

@ -4,6 +4,9 @@ Material completion denoted with 🌑🌘🌗🌖🌕 .
| # | Lecture | Materials | Exercises | | # | Lecture | Materials | Exercises |
|---:|------------------------------------------------------------------------|----------:|----------:| |---:|------------------------------------------------------------------------|----------:|----------:|
| 8 | [Inheritance and Abstract Classes](8-inheritance-and-abstract-classes.md) | 🌕 | 🌕 |
| 9 | [Interfaces](9-interfaces.md) | 🌕 | 🌕 |
| 10 | [Static Members, Methods, and Classes](10-static-members-methods-and-classes.md) | 🌕 | 🌕 |
| 11 | [Delegates and Events](11-delegates-and-events.md) | 🌕 | 🌗 | | 11 | [Delegates and Events](11-delegates-and-events.md) | 🌕 | 🌗 |
| 12 | [Files and Streams](12-files-and-streams.md) | 🌕 | 🌕 | | 12 | [Files and Streams](12-files-and-streams.md) | 🌕 | 🌕 |
| 13 | [Generics, IEnumberable and LINQ](13-generics-ienumerable-and-linq.md) | 🌕 | 🌕 | | 13 | [Generics, IEnumberable and LINQ](13-generics-ienumerable-and-linq.md) | 🌕 | 🌕 |

Loading…
Cancel
Save