--- 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: ![](imgs/7%20Classes%20and%20Objects_2.png)
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! ![](imgs/7%20Classes%20and%20Objects_3.png) ## 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); } } ```
![w:400px](imgs/7%20Classes%20and%20Objects_4.png)
--- * 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; } ``` ![](imgs/7%20Classes%20and%20Objects_5.png)
--- ![](imgs/7%20Classes%20and%20Objects_6.png) ## 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`!