---
marp: true
paginate: true
math: mathjax
theme: buutti
title: 7. Classes And Objects
---
# Classes And Objects
## Overview
* Namespaces
* Classes
* Object Variables
* Access Specifiers
* Class Members
* Constructors
* Value & Reference Types
## 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
---
* If you need a class, interface, etc to be accessible from anywhere, create it within that namespace and set it as `public`
```csharp
// Note that namespaces can have
// subdirectories, as Models here
namespace MyAwesomeApp.Models
{
public class Student
{
}
}
```
```csharp
// This is how you would use the
// Student class in other code
using MyAwesomeApp.Models
```
* Wait, what's a class, though?
## Classes
* [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)
{
}
}
```
### 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
### Creating a class
* 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__*.
### Instancing 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 class `Student` are created
* However, these objects have no functionality yet
```csharp
namespace MyAwesomeApp
{
class Student
{
}
class Program
{
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:
Student class:
```csharp
class Student
{
int id;
}
```
Error:

Program class:
```csharp
class Program
{
static void Main(string[] args)
{
Student student = new Student();
student.id = 12345678;
}
}
```
---
Let's fix the previous example by changing the *__access specifier__* of the variable `id` to `public`:
Student class:
```csharp
class Student
{
public int id;
}
```
```csharp
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
* 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
}
```
---
* 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!

## Classes: An example
```csharp
class Student
{
public int id;
public string name;
}
```
```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
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
## Class methods
* As mentioned in [Lecture 6](6-methods), we can create methods inside of our classes:
```csharp
class Person
{
public string firstName;
public string lastName;
public string FullName()
{
return firstName + " " + lastName;
}
}
```
```csharp
class Program
{
static void Main(string[] args)
{
Person someDude = new Person();
someDude.firstName = "Johannes";
someDude.lastName = "Kantola";
Console.WriteLine(someDude.FullName());
// Outputs Johannes Kantola
}
}
```
* If the method is public, it can be called from outside of the class
## Constructors
* 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:
```csharp
class User
{
public User()
{
Console.WriteLine
("New user created!");
}
}
```
```csharp
class Program
{
static void Main(string[] args)
{
User user = new User();
// Outputs "New user created!"
}
}
```
* ***Note:*** In Visual Studio, just write `ctor` and press tab twice to quickly create a constructor!
## Constructors with parameters
* You can pass in parameters to the constructor at initialization:
```csharp
class Car
{
private string model;
private int year;
private int doors;
public Car(string modelName, int modelYear)
{
model = modelName;
year = modelYear;
doors = 5;
}
}
```
```csharp
class Program
{
static void Main(string[] args)
{
Car lada = new Car("Niva", 1984);
Car ford = new Car("Focus", 2010);
// Both cars have 5 doors by default
}
}
```
## Exercise 2
1) Create a console application with a class Animal, that contains
* two strings, `name` and `sound`
* a method `Greet()` that prints ` says !` (without the angled brackets)
2) Create a few animals with different names and sounds
3) Call their greet methods from the main program
## Properties
* 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:
```csharp
class User
{
private int id;
public int Id
{
get { return id; }
set { id = value; }
}
}
```
```csharp
class Program
{
static void Main(string[] args)
{
User admin = new User();
admin.Id = 12345678;
Console.WriteLine(admin.Id);
// This outputs 12345678
}
}
```
### Auto Properties
* Auto properties are a shorthand version of the same:
```csharp
class User
{
public int Id { get; set; }
}
```
```csharp
class Program
{
static void Main(string[] args)
{
User admin = new User();
admin.Id = 12345678;
Console.WriteLine(admin.Id);
// This outputs 12345678
}
}
```
* ***Note:*** In Visual Studio, just write `prop` and press tab twice to quickly create an auto property
### Why properties?
* 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)
## Value and Reference Types
* 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
```csharp
class Program{
static void Main(string[] args)
{
int user = 1;
int otherUser = user;
user = 2;
Console.WriteLine("Value of otherUser: " + otherUser);
}
}
```

---
* Another example: When this program is executed, what will be the output?
* `string`, `Array` and Classes are of the *__reference type__
* 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
{
static void Main(string[] args)
{
User user = new User();
user.id = 1;
User otherUser = user;
user.id = 2;
Console.WriteLine(
"Value of otherUser.id: " + otherUser.id);
}
}
```
```csharp
class User
{
public int id;
}
```

---

## Exercise 3
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`!