finish lecture 7

- note: uses screenshot in slide 24
- exercise 4 removed
- add column start, middle and end code snippets
main
borb 2 weeks ago
parent 7aad3cf2d7
commit 515fc40d32

@ -107,6 +107,30 @@
"</div>", "</div>",
] ]
}, },
"marp columns start" : {
"scope": "markdown",
"prefix": "startcol",
"body" : [
"<div class='columns' markdown='1'>",
"<div markdown='1'>",
]
},
"marp columns middle" : {
"scope": "markdown",
"prefix": "midcol",
"body" : [
"</div>",
"<div markdown='1'>",
]
},
"marp columns end" : {
"scope": "markdown",
"prefix": "endcol",
"body" : [
"</div>",
"</div>",
]
},
"marp centered" : { "marp centered" : {
"scope": "markdown", "scope": "markdown",
"prefix": "centered", "prefix": "centered",

File diff suppressed because one or more lines are too long

@ -1,527 +1,581 @@
# Classes and Objects ---
marp: true
![](imgs/7%20Classes%20and%20Objects_0.png) paginate: true
math: mathjax
theme: buutti
title: 7. Classes And Objects
--- ---
# Overview # Classes And Objects
Namespaces
Classes
Object Variables
Access Specifiers
Class Members <!-- headingDivider: 5 -->
<!-- class: invert -->
Constructors ## Overview
Value & Reference Types * Namespaces
* Classes
* Object Variables
* Access Specifiers
* Class Members
* Constructors
* Value & Reference Types
Enum ## Namespaces
# Namespaces * Using namespaces helps you to organize the scope of your project, so that...
* Variable names do not clash
* Related variables are well-contained in their own namespaces
* $\Rightarrow$ easy to import what you need
* By default, when creating a new project and adding classes in Visual Studio, everything is contained within a namespace named after your project name
Using namespaces helps you to organize the scope of globally available data in your project, meaning that related objects in a well-named namespace makes it easy to import what you need ---
By default, when creating a new project and adding classes in Visual Studio, everything is contained within a namespace named after your project name * If you need a class, interface, etc to be accessible from anywhere, create it within that namespace and set it as `public`
If you need a class or an enum to be accessible from anywhere, create it within that namespace and set it as public <div class='columns' markdown='1'>
<div markdown='1'>
```csharp
// Note that namespaces can have // Note that namespaces can have
// subdirectories, as Models here // subdirectories, as Models here
namespace MyAwesomeApp.Models namespace MyAwesomeApp.Models
{
public class Student
{ {
public class Student
{
}
} }
```
} </div>
<div markdown='1'>
```csharp
// This is how you would use the // This is how you would use the
// Student class in other code // Student class in other code
using MyAwesomeApp.Models using MyAwesomeApp.Models
```
# Classes </div>
</div>
__Classes __ in C# are blueprints for a __type __ of __object__
We have already used a class named _Program _ when creating a new console application: * Wait, what's a class, though?
![](imgs/7%20Classes%20and%20Objects_1.png)
---
You could even create new instances of Program
* If we wanted, we could just write the entire program with thousands of lines of code on one page inside the main function
* This kind of program would of course be impossible to work with within a group or organization:
* No one should have to scroll through tens of thousands of lines of code to find that one line that causes problems…
* At least make them browse through hundreds of classes instead :)
* Classes provide __encapsulation __ which result in __shorter files__ , __less repetitive code__ and overall __better readability__
# Creating a Class ## Classes
You can create a new class by writing * [Classes](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/classes) in C# are blueprints for specific kinds of collections of data & functionality
* ***Instance*** of a class is an implementation of that class, also referred to as an ***object***
* As C# is an object-oriented language, almost everything has to happen in a class
* Thus, we have already used a class named `Program` when creating a new console application:
```csharp
class Program
{
static void Main(string[] args)
{
class Student }
}
```
{ ### Why classes?
} * Classes are a core feature of the ***object-oriented programming*** paradigm popularized by Java in the 90s
* (See [Lecture 8](8-inheritance-and-abstract-classes#extra-object-oriented-programming))
* Classes provide *__encapsulation__*: Connected concepts and functionalities are neatly contained within a class
* This will ***ideally*** result in shorter files, less repetitive code and ***hopefully*** overall better readability
* No paradigm is idiot-proof, though...
* Shorter files can also mean that it's hard to find the actual functionality from hundreds of short files full of intermediate classes and class factories
Create variables inside a class just like before inside the Program class: ### Creating a class
class Student * You can create a new class by writing
```csharp
class Student
{
{ }
```
* Create variables inside a class just like before inside the `Program` class:
```csharp
class Student
{
int id;
string name;
}
```
* These variables declared directly inside classes are called *__fields__*.
int id; ### Instancing a class
string name; <div class='columns' markdown='1'>
<div markdown='1'>
} * New instances of a class can be created with the `new` keyword
* All instances of a class have exactly the same fields and methods, but they can have different values
* In the following example a few ***objects*** of class `Student` are created
* However, these objects have no functionality yet
</div>
<div markdown='1'>
Variables declared directly inside classes are called __fields.__ ```csharp
# Referencing a Class
New instances of a class can be created with the __new __ keyword
All instances of a class have exactly the same fields and methods, but they can have different values
In the following example a few __objects __ of __type __ Student are created
However, these objects have no functionality yet
namespace MyAwesomeApp namespace MyAwesomeApp
{
class Student
{ {
class Student
{
}
class Program
{
static void Main(string[] args)
{
Student student1 = new Student();
Student student2 = new Student();
Student student3 = new Student();
}
}
} }
```
class Program </div>
</div>
{
static void Main(string[] args)
{
Student student1 = new Student();
Student student2 = new Student();
Student student3 = new Student(); ### Object variables
} * Variables inside of an object can be accessed with the `.` operator
* However, the following syntax results in an error:
} <div class='columns' markdown='1'>
<div markdown='1'>
Student class:
```csharp
class Student
{
int id;
} }
```
# Object Variables Error:
The variables inside of an object can be accessed with the '.' operator
However, the following syntax results in an error:
| Student class: | Program class: |
| :-: | :-: |
| class Student{ int id;} | class Program{static void Main(string[] args){ Student student = new Student(); student.id = 12345678;}} |
![](imgs/7%20Classes%20and%20Objects_2.png) ![](imgs/7%20Classes%20and%20Objects_2.png)
Let's fix the previous example by changing the _ _ __access specifier__ of the 'id' variable to __public__ :
| Student class: | Program class: |
|:---------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
| class Student{ public int id;} | class Program{static void Main(string[] args){ Student student = new Student(); student.id = 12345678;}} |
| | |
The value of the variable 'id' of the object 'student' is now 12345678
# Access Specifiers
__Access specifiers__ can be used to get additional level of protection inside classes
Variables specified with __private __ are accessible only inside the containing class
Variables specified with __public __ are accessible outside of the class </div>
<div markdown='1'>
The __default __ access for any variable is private! Program class:
class Student
```csharp
class Program
{ {
static void Main(string[] args)
{
Student student = new Student();
student.id = 12345678;
}
}
```
int id; // Accessible only inside the class </div>
</div>
private string name; // Accessible only inside the class
public string address; // Accessible everywhere within the namespace
} ---
Continuing on the class in the previous slide, if we follow the 'student' variable with a dot, VS intellisense will only suggest the 'address' variable, because it was the only public variable of the 'Student' class Let's fix the previous example by changing the *__access specifier__* of the variable `id` to `public`:
![](imgs/7%20Classes%20and%20Objects_3.png)
# Classes - Example <div class='columns' markdown='1'>
<div markdown='1'>
Student class:
```csharp
class Student class Student
{ {
public int id;
public int id;
public string name;
} }
```
class Program </div>
<div markdown='1'>
```csharp
class Program
{ {
static void Main(string[] args)
{
Student student = new Student();
student.id = 12345678;
}
}
```
static void Main(string[] args) </div>
</div>
{ * The value of the variable `id` of the object `student` is now `12345678`
Student student1 = new Student(); ## Access Specifiers
Student student2 = new Student(); * *__Access specifiers__* can be used to get additional level of protection inside classes
* Variables specified with `private` are accessible only inside the containing class
* This is the ***default*** access!
* Variables specified with `public` are accessible outside of the class
```csharp
class Student
{
int id; // Accessible only inside the class
private string name; // Accessible only inside the class
public string address; // Accessible everywhere within the namespace
}
```
student1.id = 22225555; ---
student1.name = "Johannes Kantola"; * Continuing on the class in the previous example: if we follow the `student` variable with a dot, Visual Studio IntelliSense will only suggest the `address` variable, because it was the only `public` variable of the `Student` class!
student2.id = 44441111; ![](imgs/7%20Classes%20and%20Objects_3.png)
student2.name = "Rene Orosz"; ## Classes: An example
Console.WriteLine(student1.name); // Outputs Johannes Kantola <div class='columns12' markdown='1'>
<div markdown='1'>
```csharp
class Student
{
public int id;
public string name;
} }
```
</div>
<div markdown='1'>
```csharp
class Program
{
static void Main(string[] args)
{
Student student1 = new Student();
Student student2 = new Student();
student1.id = 22225555;
student1.name = "Johannes Kantola";
student2.id = 44441111;
student2.name = "Rene Orosz";
Console.WriteLine(student1.name);
// Outputs Johannes Kantola
}
} }
```
# Exercise 1 </div>
</div>
Create a console application that has a class User which contains two fields: string userName and string password ## Exercise 1
<!--_class: "exercise invert" -->
Create a main loop where the user is asked repeatedly for a new username and password. The values are stored to a new User instance and that instance is saved to a list of users 1) Create a console application that has a class `User` that contains two fields: `string userName` and `string password`
2) Create a main loop where the user is asked repeatedly for a new username and password. The values are stored in a new `User` instance and that instance is saved to a list of users
3) Print all stored usernames every time a new user is created
Print all stored usernames every time a new user is created ## Class methods
# Class Methods * As mentioned in [Lecture 6](6-methods), we can create methods inside of our classes:
As mentioned in the previous lecture, we can create methods inside of our classes: <div class='columns' markdown='1'>
<div markdown='1'>
```csharp
class Person class Person
{
public string firstName;
public string lastName;
public string FullName()
{ {
public string firstName;
return firstName + " " + lastName; public string lastName;
public string FullName()
{
return firstName + " " + lastName;
}
} }
```
} </div>
<div markdown='1'>
```csharp
class Program class Program
{
static void Main(string[] args)
{ {
static void Main(string[] args)
Person someDude = new Person(); {
Person someDude = new Person();
someDude.firstName = "Johannes"; someDude.firstName = "Johannes";
someDude.lastName = "Kantola";
someDude.lastName = "Kantola"; Console.WriteLine(someDude.FullName());
// Outputs Johannes Kantola
Console.WriteLine(someDude.FullName()); }
// Outputs Johannes Kantola
} }
```
} </div>
</div>
If the method is public, it can be called from outside of the class * If the method is public, it can be called from outside of the class
# Constructors ## Constructors
Constructors are class methods which are called once the object is initialized * Constructors are class methods which are called once the object is initialized
* Constructors are created by creating a class method with the same name as the class:
Constructors are created by creating a class method with the same name as the class: <div class='columns' markdown='1'>
<div markdown='1'>
```csharp
class User class User
{
public User()
{ {
public User()
Console.WriteLine {
Console.WriteLine
("New user created!"); ("New user created!");
}
} }
```
} </div>
<div markdown='1'>
| | |
| :-: | :-: |
```csharp
class Program class Program
{
static void Main(string[] args)
{ {
static void Main(string[] args)
User user = new User(); {
User user = new User();
// Outputs "New user created!" // Outputs "New user created!"
}
} }
```
} </div>
</div>
* ***Note:*** In Visual Studio, just write `ctor` and press tab twice to quickly create a constructor!
In Visual Studio, just write "ctor" and press tab twice to quickly create a constructor ## Constructors with parameters
# Constructors with Parameters * You can pass in parameters to the constructor at initialization:
You can pass in parameters to the constructor at initialization: <div class='columns' markdown='1'>
<div markdown='1'>
```csharp
class Car class Car
{
private string model;
private int year;
private int doors;
public Car(string modelName, int modelYear)
{ {
private string model;
private int year;
private int doors;
model = modelName; public Car(string modelName, int modelYear)
{
year = modelYear; model = modelName;
year = modelYear;
doors = 5; doors = 5;
}
} }
```
} </div>
<div markdown='1'>
```csharp
class Program class Program
{
static void Main(string[] args)
{ {
static void Main(string[] args)
Car lada = new Car("Niva", 1984); {
Car lada = new Car("Niva", 1984);
Car ford = new Car("Focus", 2010); Car ford = new Car("Focus", 2010);
// Both cars have 5 doors by default
// Both cars have 5 doors by default }
}
} }
```
</div>
</div>
# Exercise 2 ## Exercise 2
<!--_class: "exercise invert" -->
Create a console application with a class Animal, that contains
two strings: name and sound, and
a method Greet() that prints " __*name*__ says __*sound*__ !" 1) Create a console application with a class Animal, that contains
* two strings, `name` and `sound`
* a method `Greet()` that prints `<name> says <sound>!` (without the angled brackets)
2) Create a few animals with different names and sounds
3) Call their greet methods from the main program
Create a few animals with different names and sounds ## Properties
Call their greet methods from the main program * When working with C#, you will eventually see [properties](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties) being used at some point
* They are fields with defined `get` and `set` ***accessors***
* These accessors are often referred to as a ***getter*** and a ***setter***
* Properties allow the manipulation of private fields from outside of the class:
# Properties <div class='columns' markdown='1'>
<div markdown='1'>
When working with C#, you will eventually see __properties __ being used at some point
Properties allow the manipulation of private fields from outside of the class:
```csharp
class User class User
{ {
private int id;
private int id; public int Id
{
public int Id get { return id; }
set { id = value; }
{ }
get { return id; }
set { id = value; }
} }
```
} </div>
<div markdown='1'>
```csharp
class Program class Program
{
static void Main(string[] args)
{ {
static void Main(string[] args)
User admin = new User(); {
User admin = new User();
admin.Id = 12345678; admin.Id = 12345678;
Console.WriteLine(admin.Id);
Console.WriteLine(admin.Id); // This outputs 12345678
}
// This outputs 12345678
} }
```
} ### Auto Properties
# Auto Properties * Auto properties are a shorthand version of the same:
Auto properties are a shorthand version of the same: <div class='columns' markdown='1'>
<div markdown='1'>
```csharp
class User class User
{ {
public int Id { get; set; }
public int Id { get; set; }
} }
```
class Program </div>
<div markdown='1'>
```csharp
class Program
{ {
static void Main(string[] args)
{
User admin = new User();
admin.Id = 12345678;
Console.WriteLine(admin.Id);
// This outputs 12345678
}
}
```
static void Main(string[] args) </div>
</div>
{ * ***Note:*** In Visual Studio, just write `prop` and press tab twice to quickly create an auto property
User admin = new User(); ### Why properties?
admin.Id = 12345678; * Why use properties if we could just use public fields?
* We don't always want to expose the exact same variable that is used inside the class to outside
* Properties allow class fields to be *__read-only__* or *__write-only__*:
```csharp
public int Id { get; } // This field is read-only
public int Password { private get; set; } // This field is write-only
```
* Also, we can add whatever functionality we want to getters and setters, which makes properties a very flexible feature
* Don't know when a property is being changed? Just print its value to the console in the setter.
* Properties are supported in *__interfaces__*, while fields are not
* We will cover interfaces later in [Lecture 9](9-interfaces#interfaces)
Console.WriteLine(admin.Id); ## Value and Reference Types
// This outputs 12345678 * See the example below. If this program is executed, what will be the output?
* `int`, `double`, `char` and other primitive data types are of the *__value type__*
* The variable stores the *__actual data__* in memory
* Every copy of the variable will be stored in a separate location
} <div class='columns21' markdown='1'>
<div markdown='1'>
```csharp
class Program{
static void Main(string[] args)
{
int user = 1;
int otherUser = user;
user = 2;
Console.WriteLine("Value of otherUser: " + otherUser);
}
} }
```
</div>
<div markdown='1'>
In Visual Studio, just write "prop" and press tab twice to quickly create an auto property ![w:400px](imgs/7%20Classes%20and%20Objects_4.png)
# Properties </div>
</div>
* __Why use properties if we could just use public fields?__
* We don't always want to expose the exact same variable that is used inside of the class, to outside
* Properties allow class fields to be __read-only__ or __write-only__ :
* public int Id { get; } // This field is read-onlypublic int Password { private get; set; } // This field is write-only
* Properties are supported in __interfaces__ , while fields are not
* We will cover interfaces later
* There are a bunch of other reasons, but they are outside the scope of this course
--- ---
Lets say we have a variable in our class which is queued for calculating something important * Another example: When this program is executed, what will be the output?
Now some other class changes that variable -> Problem * `string`, `Array` and Classes are of the *__reference type__
* The variable stores ***the address of the data*** being stored in memory
# Value and Reference Types * Every copy of the variable points to the same ***address***
* If this program is executed, what will be the output?
* int, double, char and other primitive data types are of __value type__
* The variable stores the __actual data__ in memory
* Every copy of the variable will be stored in a separate location
* class Program{ static void Main(string[] args) { int user = 1; int otherUser = user; user = 2; Console.WriteLine( "Value of otherUser: " + otherUser); }}
![](imgs/7%20Classes%20and%20Objects_4.png)
* When this program is executed, what will be the output? <div class='columns' markdown='1'>
* Strings, Arrays and Classes are of __reference type __ <div markdown='1'>
* The variable stores the address of the data being stored in memory
* Every copy of the variable points to the same address
```csharp
class Program class Program
{
static void Main(string[] args)
{ {
static void Main(string[] args)
User user = new User(); {
User user = new User();
user.id = 1; user.id = 1;
User otherUser = user;
User otherUser = user; user.id = 2;
Console.WriteLine(
user.id = 2; "Value of otherUser.id: " + otherUser.id);
}
Console.WriteLine(
"Value of otherUser.id: " + otherUser.id);
} }
```
} </div>
<div markdown='1'>
```csharp
class User class User
{ {
public int id;
public int id;
} }
```
![](imgs/7%20Classes%20and%20Objects_5.png) ![](imgs/7%20Classes%20and%20Objects_5.png)
Location in memory </div>
</div>
---
![](imgs/7%20Classes%20and%20Objects_6.png)
<!-- Location in memory
int userId = 42; int userId = 42;
@ -542,17 +596,17 @@ User user = new User(42);
User otherUser = user; User otherUser = user;
| user { id = 42 } | | user { id = 42 } |
| :-: | | :-: | -->
# Exercise 3
Classes and enums can be created to a separate file. To quickly create a new class, right mouse click you project (not solution) name in solution explorer -> Add -> Class… Name your class "TestClass"
Back in your main method, create an instance of TestClass. The compiler should not give any errors. ## Exercise 3
<!--_class: "exercise invert" -->
Now rename the namespace that your TestClass is in, to "TestNamespace". Go back to your main method. The TestClass instantiation should not work anymore. Try to fix that without going back to TestClass. 1) Classes can be stored in a separate file. To quickly create a new class in Visual Studio: right mouse click your project name (not the solution!) in Solution Explorer *-> Add -> Class...*
* Name your class `TestClass`.
2) Back in your main method, create an instance of `TestClass`. The compiler should not give any errors.
3) Now rename the namespace that your `TestClass` is in to `TestNamespace`. Go back to your main method. The `TestClass` instantiation should not work anymore. Try to fix the issue without going back to `TestClass`!
# Exercise 4 <!-- ## Exercise 4
Modify previous solution by using methods and class. Modify previous solution by using methods and class. -->

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Loading…
Cancel
Save