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
      • 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
// Note that namespaces can have
// subdirectories, as Models here

namespace MyAwesomeApp.Models
{
  public class Student
  {

  }
}
// This is how you would use the
// Student class in other code

using MyAwesomeApp.Models
  • Wait, what's a class, though?

Classes

  • 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:
    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
  • 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
    class Student
    {
    
    }
    
  • Create variables inside a class just like before inside the Program class:
    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

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:
class Student
{
  int id;
}

Error:

Program class:

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:
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
    • This is the default access!
  • Variables specified with public are accessible outside of the class
    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

class Student
{
  public int id;
  public string name;
}
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, we can create methods inside of our classes:
class Person
{
  public string firstName;
  public string lastName;
  public string FullName()
  {
    return firstName + " " + lastName;
  }
}
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:
class User
{
  public User()
  {
    Console.WriteLine
      ("New user created!");
  }
}
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:
class Car
{
  private string model;
  private int year;
  private int doors;

  public Car(string modelName, int modelYear)
  {
    model = modelName;
    year = modelYear;
    doors = 5;
  }
}
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 <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

Properties

  • When working with C#, you will eventually see 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:
class User
{
  private int id;
  public int Id
  {
    get { return id; }
    set { id = value; }
  }
}
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:
class User
{
  public int Id { get; set; }
}
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:
    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

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
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
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);
  }
}
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!

Location in memory int userId = 42; int otherUserId = userId; | 42 | | :-: | | 42 | Changing the value in the object will affect all variables referencing it! | points to | | :-: | | points to | User user = new User(42); User otherUser = user; | user { id = 42 } | | :-: |

## Exercise 4 Modify previous solution by using methods and class.