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
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:
class MyAwesomeClass
{
public int MyProperty { get; set; }
}
class Program
{
static void Main(string[] args)
{
MyAwesomeClass instance1 = new MyAwesomeClass();
MyAwesomeClass instance2 = new MyAwesomeClass();
instance1.MyProperty = 100;
instance2.MyProperty = 200; // instance1.MyProperty is still 100
}
}
# Static Members (continued)
Likewise, non-static class methods _have to _ be called through an instance:
class MyAwesomeClass
{
public void PrintText(string text) { Console.WriteLine(text); }
}
class Program
{
static void Main(string[] args)
{
MyAwesomeClass instance = new MyAwesomeClass();
instance.PrintText("Hello World"); // Outputs "Hello World"
MyAwesomeClass.PrintText("Hello World"); // Results in an error
}
}
![](imgs/10%20Static%20Members%2C%20Methods%20and%20Classes_1.png)
__Static fields are shared between all instances of a class__
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:
class MyAwesomeClass
{
public static int MyProperty { get; set; } = 100;
}
class Program
{
static void Main(string[] args)
{
MyAwesomeClass instance = new MyAwesomeClass();
Console.WriteLine(MyAwesomeClass.MyProperty); // Outputs "100"
Console.WriteLine(instance.MyProperty); // Results in an error
}
}
![](imgs/10%20Static%20Members%2C%20Methods%20and%20Classes_2.png)
# Static Members - Example
In this example, a static field is used for keeping count on how many times the class has been instantiated:
class Person
{
public static int totalPersons = 0;
private string name;
public Person(string personName) // Person Constructor
{
name = personName;
++totalPersons;
}
public void PrintInfo()
{
Console.WriteLine("This person is called " + name + ".");
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
{
static void Main(string[] args)
{
Person steve = new Person("Steve");
Person wendy = new Person("Wendy");
steve.PrintInfo(); <!-- headingDivider: 5 -->
<!-- class: invert -->
## Static Members
### 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; }
}
class Program
{
static void Main(string[] args)
{
MyAwesomeClass instance1 = new MyAwesomeClass();
MyAwesomeClass instance2 = new MyAwesomeClass();
instance1.MyProperty = 100;
instance2.MyProperty = 200; // instance1.MyProperty is still 100
}
}
```
wendy.PrintInfo(); ---
} * Likewise, non-static class methods **_have to_** be called through an instance:
```csharp
class MyAwesomeClass
{
public void PrintText(string text)
{
Console.WriteLine(text);
}
}
class Program
{
static void Main(string[] args)
{
MyAwesomeClass instance = new MyAwesomeClass();
instance.PrintText("Hello World"); // Outputs "Hello World"
MyAwesomeClass.PrintText("Hello World"); // Results in an error
}
}
```
<div class='centered'>
![w:500px](imgs/10%20Static%20Members%2C%20Methods%20and%20Classes_1.png)
</div>
### 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
{
public static int MyProperty { get; set; } = 100;
}
class Program
{
static void Main(string[] args)
{
MyAwesomeClass instance = new MyAwesomeClass();
Console.WriteLine(MyAwesomeClass.MyProperty); // Outputs "100"
Console.WriteLine(instance.MyProperty); // Results in an error
}
}
```
<div class='centered'>
![w:600px](imgs/10%20Static%20Members%2C%20Methods%20and%20Classes_2.png)
</div>
### 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;
private string name;
public Person(string personName) // Person Constructor
{
name = personName;
++totalPersons;
}
public void PrintInfo()
{
Console.WriteLine("This person is called " + name + ".");
Console.WriteLine("There are " + totalPersons + " persons total.");
}
}
```
} ---
![](imgs/10%20Static%20Members%2C%20Methods%20and%20Classes_3.png)
# Static Methods
Methods can also be static * Now let's instantiate a couple of persons and print their info:
What happens when you try to call a non-static method from a static method? <div class='columns21' markdown='1'>
<div markdown='1'>
```csharp
class Program class Program
{
void PrintHelloName(string name)
{ {
static void Main(string[] args)
Console.WriteLine("Hello, " + name); {
Person steve = new Person("Steve");
} Person wendy = new Person("Wendy");
steve.PrintInfo();
static void Main(string[] args) wendy.PrintInfo();
}
{ }
```
PrintHelloName(); // Will throw an error
</div>
} <div markdown='1'>
} ![w:400px](imgs/10%20Static%20Members%2C%20Methods%20and%20Classes_3.png)
![](imgs/10%20Static%20Members%2C%20Methods%20and%20Classes_4.png) </div>
</div>
---
## Static methods
This is why until this point all example methods have been inside of the main function
* Methods can also be static
# Static Classes * What happens when you try to call a non-static method from a static method?
```csharp
* Classes can also be made static class Program
* Static classes cannot be instantiated {
* All members of a static class also have to be static void PrintHelloName(string name)
* static class Styling {
* { Console.WriteLine("Hello, " + name);
* public static string fontFamily = "Verdana"; }
* public static float fontSize = 12.5f; static void Main(string[] args)
* } {
* class Program PrintHelloName(); // Will throw an error
* { }
* static void Main(string[] args) }
* { ```
* Console.WriteLine
* ("Using font " + Styling.fontFamily + " " + Styling.fontSize + "px"); <div class='centered'>
* // Outputs "Using font Verdana 12.5px"
* Styling = new Styling(); // Results in an error ![w:800px](imgs/10%20Static%20Members%2C%20Methods%20and%20Classes_4.png)
* }
* } </div>
# Exercise 1 ## Static classes
Create a class Message which has two __static __ properties int TotalMessages and string LastMessage, and a __non-static __ property string MessageText. * Whole classes can also be static
* Static classes cannot be instantiated, and all its members have to be static as well
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 ```csharp
static class Styling
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: {
public static string fontFamily = "Verdana";
Message newMessage = new Message(message); public static float fontSize = 12.5f;
}
newMessage is then added to a list of messages, allMessages class Program
{
Finally the static values Message.TotalMessages and Message.LastMessage are printed 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
<!--_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);
```
* `newMessage` is then added to a list `allMessages`.
* 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() { Console.WriteLine("Bark!"); }
}
class Program
{
static void Main(string[] args)
{
Dog pluto = new Dog();
pluto.Eat(); // Outputs "Eating..."
pluto.Bark(); // Outputs "Bark!"
}
}
# Inheritance
All the objects deriving from the same base class can be referenced with the base class name:
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:
plutoAnimal.Eat(); // Outputs "Eating..."
plutoAnimal.Bark(); // Error
An object of base class type can be __casted __ into the child class type:
Dog pluto = (Dog)plutoAnimal;
pluto.Bark(); // Outputs "Bark!"
# 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:
abstract class Animal
{ {
public void Bark()
public void Eat() { Console.WriteLine("Eating..."); } { Console.WriteLine("Bark!"); }
public void Sleep() { Console.WriteLine("Sleeping..."); }
} }
```
class Pig : Animal </div>
<div markdown='1'>
{
public void Squeal() { Console.WriteLine("Squeee!"); }
}
```csharp
class Program class Program
{ {
static void Main(string[] args)
static void Main(string[] args) {
Dog pluto = new Dog();
{ pluto.Eat(); // Outputs "Eating..."
pluto.Bark(); // Outputs "Bark!"
Pig pig = new Pig(); }
pig.Sleep(); // Outputs "Sleeping..."
pig.Squeal(); // Outputs "Squeee!"
} }
```
}
</div>
If you know you only need the functionality of the abstract class, instantiate the new class as a type of abstract class: </div>
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 }} ### 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
}
}
```
--- ---
This is called abstraction, which is one of the key concepts of OOP * Instead, the methods are accessible through a derived 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
{
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!"
}
}
```
Create a few instances of Dog, Cat and Pig classes, and add them to a new list of Animals, named "allAnimals" ---
Loop through allAnimals with the foreach statement, and call the Greet() method of each animal
# Enum
__Enum __ (short for enumeration) is a data type for holding a set of constant (immutable) names
Enums can be useful when you have a number of items or states that are predefined, for example, weekdays
Create the enum type with the enum keyword:
enum Weekday{ Monday, Tuesday, Wednesday, Thursday, Friday, Saturday}
New instances of the enum can only be assigned one of the values within:
Weekday currentDay = Weekday.Monday;
# Enum - Example
In this example, enum is used to keep track of the state of the program:
* 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 enum ProgramState
{ {
Login,
Login, Menu,
Exit
Menu,
Exit
} }
```
static void Main(string[] args) </div>
<div markdown='1'>
{
ProgramState currentState = ProgramState.Login;
while (true)
{
switch (currentState)
```csharp
static void Main(string[] args)
{ {
ProgramState currentState = ProgramState.Login;
case ProgramState.Login: while (true)
{
// Switch current state to Menu after logging in switch (currentState)
{
break; case ProgramState.Login:
// Switch current state to Menu after logging in
case ProgramState.Menu: break;
case ProgramState.Menu:
// Switch current state to Exit if user exits // Switch current state to Exit if user exits
break;
break; case ProgramState.Exit:
// Exit the program with an exit message
case ProgramState.Exit: break;
}
// Exit the program with an exit message }
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:
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 * Implement an interface just like you would inherit a class:
```csharp
class User : IUser
{
Let's fix that by defining those now }
```
* 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
# Implementing an Interface (continued) ---
```csharp
class User : IUser class User : IUser
{
public int Id { get; set; }
public string Name { get; set; }
public void GetUserStatistics()
{ {
public int Id { get; set; }
// Some code here 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_.
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 ### Why use interfaces?
Consider the following example: * 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
public void DeleteData(IDeletable data) * Consider the following example:
```csharp
{ 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'>
{
public void Move()
```csharp
class Elephant : IMovable
{ {
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()
{
Console.WriteLine("The cat is moving'");
}
public void Carry()
{ {
public void Move()
Console.WriteLine("You are carrying the cat"); {
Console.WriteLine("The cat is moving'");
}
public void Carry()
{
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");
} }
```
} </div>
</div>
class Program
{ ---
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 =
List<IMovable> movables = new List<IMovable>{ elephant, cat }; new List<IMovable>{ elephant, cat };
List<ICarryable> carryables =
List<ICarryable> carryables = new List<ICarryable>{ cat, rock }; 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();
} }
```
} </div>
<div markdown='1'>
![](imgs/9%20Interfaces_1.png) ![](imgs/9%20Interfaces_1.png)
# Exercise 1: A Web of Relations </div>
</div>
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 ## Exercise 1: A web of relations
<!--_class: "exercise invert" -->
Create a list of type IInfo, and add the products and categories to it Create a console application that has an interface `IInfo` and two classes `Product` and `Category` that both implement `IInfo`.
Create a main loop, where each time the user presses enter, all the info texts inside the list are printed 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 ## 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. 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. 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`.
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" -->
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. 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