If you're like me and can't seem to wrap your head around "classes" then I hope these magical examples can serve as some kind of reference for the both of us!
In this post, I'll be using some wizard-themed examples to try and make a reference for myself and others so we can finally "get" classes.
This post will just cover the basics of classes and objects, there will be further posts explaining more advanced topics.
Classes and Objects
First of all, why do we even need classes?
To put it simply, they keep related bits of code and info together, so everything is neat and easy to find. Pretty convenient, right?
Of course, there's a lot more to it than that, I suggest checking out some of these resources to learn more about classes and objects.
- Codecademy's C# Classes & Objects - free course
- Object Oriented Programming: Objects and Classes - video
- W3Schools C# Classes and Objects - free course
After you have an idea about what classes and objects are, check out the "Wizard" class belowđ
Wizard Class
Imagine you wanted to represent every witch or wizard in the Harry Potter universe. You could create a class to define their common characteristics.
public class Wizard
{
private int age; // This is a backing field for the Age property
// what's a backing field??đ
see Example 1 below
// Properties
public string Name { get; set; }
public string House { get; set; }
public string Pet { get; set; }
// what the heck do get and set do?? see Example 2
public int Age
{
get
{
return age;
}
set
{
if (value >= 11 && value <= 150)
{
age = value;
}
else
{
Console.WriteLine("Invalid age for a wizard at Hogwarts.");
}
}
}
public string WandType { get; set; }
// Methods
public void CastSpell(string spellName)
{
Console.WriteLine($"{Name} casts {spellName}!");
}
}
Here, "Wizard" is a class that has properties like "Name", "House", "Age", and "WandType". It also has the method "CastSpell" to represent the action of a witch or wizard casting a spell.
The "age" field is private and is used to store the actual value of a wizard's age. When we want to set or get the age of a wizard, we use the public "Age" property.
The set accessor in the "Age" property contains logic to validate the age. If someone tries to set an age value less than 11 or more than 150, the class will print an error message, and the age won't be changed.
But why should we have a private AND a public Age? Why do we even need a backing field?
Look at this part of the "Wizard" class again:
private int age; // Backing field
public int Age
{
get { return age; }
set
{
if (value >= 11 && value <= 150)
{
age = value;
}
else
{
Console.WriteLine("Invalid age for a wizard at Hogwarts.");
}
}
}
We are using a backing field ("age"). The "age" variable is the backing field for the "Age" property. The backing field is necessary here to store the value of "Age" when it's set, and to return the value when it's accessed.
The key point about using a backing field is that it allows you to have control over how the value is stored and accessed, enabling you to add additional logic (like validation) as needed.
If you were to try and define the "Age" property without a backing field:
public int Age
{
get { return Age; }
set
{
if (value >= 11 && value <= 150)
{
Age = value;
}
else
{
Console.WriteLine("Invalid age for a wizard at Hogwarts.");
}
}
}
You would end up with a recursive call that would result in a StackOverflowException. This happens because when you try to get or set the age, it just ends up trying to get or set the age again, creating an infinite loop.
Using a backing field avoids this issue, because in the get and set accessors, we have a separate variable (age), not the property itself.
If this is still confusing, check out Example 1 below.
Wizard Objects
Now, if we want to represent both Harry Potter and Hermione Granger in our program, we need to create two objects (or instances) of the "Wizard" class:
Wizard harry = new Wizard
{
Name = "Harry Potter",
House = "Gryffindor",
Age = 17,
WandType = "Holly with a phoenix feather core",
Pet = "Hedwig the owl"
};
Wizard hermione = new Wizard
{
Name = "Hermione Granger",
House = "Gryffindor",
Age = 17,
WandType = "Vine wood with a dragon heartstring core",
Pet = "Crookshanks the cat"
};
harry.CastSpell("Expelliarmus");
// Output: Harry Potter casts Expelliarmus!
Console.WriteLine($"{hermione.Name} has a pet named {hermione.Pet}");
// Output: Hermione Granger has a pet named Crookshanks the cat
In this example, "harry" and "hermione" are objects of the Wizard class. We set their properties individually, giving each wizard their own unique characteristics. After that, Harry casts a spell using the "CastSpell" method, and we also display the name of Hermioneâs pet cat, Crookshanks, using the properties of the "hermione" object.
Examples:
Example 1: Backing field
Imagine a backing field as Tom Riddleâs diary.
Diary (Backing Field): Just like how Tom Riddle put his thoughts and secrets into the diary, your private data is stored securely. Itâs meant to be accessed and modified only within safe and controlled conditions.
Tom Riddle's manifestation (Property): If someone at Hogwarts, let's say Ginny, wants to delve into the diaryâs mysteries, she wouldnât directly read from its pages. Instead, she would interact with Tom Riddleâs manifestation, which represents the property in C#. Depending on the circumstances, Tom might alter the information, hold back details, or even choose to remain silent.
In coding:
The diary is like the backing field. It holds the actual data.
Tomâs manifestation acts as the property, controlling access to the diaryâs content. Other parts of the code (aka other characters in the story) must communicate with Tom to access or modify the diary's content. However, the ability to access or change the content is based on specific conditions.
Example 2: Accessors (get and set)
Think of the thermostat in your home:
get: When you look at the thermostat, you can see the current room temperature. This is like the get accessor â it allows you to view the value.
set: If you want the room to be warmer or cooler, you adjust the thermostat to the desired temperature. However, there are limits on how high or low you can set the temperature. For example, it might only go as low as 50°F and as high as 90°F. If you try to set it outside these limits, it won't let you. Thatâs how the set accessor works, the information needs to be validated before it is actually set.
In our "Wizard" class, the "Age" property is similar. When we "get" the age, it's like checking the current temperature. But when we "set" the age, we ensure it's a valid age (between 11 and 150), just as the thermostat ensures the temperature is within its limits.
Here's a simple wizard example about how get and set work:
public class Wizard
{
private string favoriteSpell; // Backing field
public string FavoriteSpell
{
get
{
return "The favorite spell is: " + favoriteSpell;
}
set
{
if (string.IsNullOrEmpty(value))
{
Console.WriteLine("A wizard must have a favorite spell!");
}
else
{
favoriteSpell = value;
}
}
}
}
// Using the class
Wizard ron = new Wizard();
ron.FavoriteSpell = "Wingardium Leviosa";
// Sets rons favorite spell
Console.WriteLine(ron.FavoriteSpell);
// Gets rons favorite spell
// Output: The favorite spell is: Wingardium Leviosa
In this example:
- The "FavoriteSpell" property uses get to retrieve and display the wizards favorite spell.
- The set accessor checks if the provided spell is null or empty. If it is, it gives a message that a wizard must have a favorite spell; otherwise, it sets the favorite spell.
Also, itâs important to note that C# has a shortcut for when you donât need extra logic in your get or set. Instead of writing out the whole thing with a backing field and validation, you can do something like this:
public string Wand { get; set; }
Here, a hidden backing field is automatically created for the "Wand" property. This keeps code concise, but if you need to add validation or other logic, you would need to create a backing field and switch to the full property syntax.
Well, thats all for this post. I recommend trying to make your own classes and objects. By doing this, you'll deepen your understanding and see how everything fits together.
If you have any suggestions for how to improve this post or notice anything I have excluded that should be considered basic knowledge when it comes to classes and objects please let me know đ
If you're looking for more resources to learn how to code check out my Free Coding Resources site, it has links to a bunch of my favorite courses/resources!
If you have any questions or want to connect, the best place to reach me is on Twitter/X.
Happy coding!