If you’ve been following some of my other posts about Unity game development, you’re probably turning to this post to learn about the basics of coding. Alternatively, you could’ve ended up on this page because you’re interested in coding. In that case, If you’re interested in game development, I’ll show you just how coding can be utilized with practical examples.
Today, I’ll go over the most common concepts in the context of coding or programming. To do that, I’ll be looking at one of the most popular programming languages in the world: C#.
This post will focus on the C# programming language, but most of these concepts apply to other object oriented programming languages as well. So don’t worry, I’ll go over the syntax briefly, but you’ll be able to translate most concepts to other languages easily.
Syntax
What is syntax, exactly?
Well, syntax refers to the structure of the statements in a computer language. In this case, we’ll be looking at C#.
In the C# programming languages, we often encounter several types of brackets.
Sometimes you’ll find curly brackets, like ‘{‘ and ‘}’. These curly brackets symbolize the start and end of a code block. These can also be nested, for example when you find a method inside a class inside a namespace. Don’t worry about what that means yet, I’ll go over that later. For now, it’s important that you know those curly brackets provide structure in your code.
Another type of bracket you’ll find are these: ‘(‘ and ‘)’. These brackets usually symbolize the start and end of parameters of methods.
There are other types of brackets as well, and other use cases for the ones already mentioned, but that’s for another post since they will only confuse things unnecessarily. Here I will only focus on basics and object oriented programming.
The semicolon ‘;’ is one of the most common characters you’ll find in the C# language. This signifies the end of a statement. A statement is a small piece of code, usually only one line long, but it can be longer. You can have several statements on a single line, if seperated by a semicolon, but for readability, it’s recommended to use a new line per statement.
In the C# programming language, as well as many others, you’ll often see words, that are stringed together with a dot (.). The reason for this is to reflect the code structure as defined by the curly brackets I explained earlier. Since blocks of code can be nested into each other, you need a way to refer to them. So whenever you see a dot, know that what follows the dot is part of what comes before it, be it a class or a method or property.
A few things we’ll find in C# files are namespaces, classes, properties and methods. These generally follow the same structure in writing, which is usually one or more access modifiers, a (return) type and a symbol.
Access to the components of your code are protected by what’s called “access modifiers”. The most common ones are “public”, “private”, “protected”, “internal”, “abstract”, “virtual” and “override”. If you’re just learning about C# and don’t intend to use it in a professional capacity, I wouldn’t worry about it too much. To make sure everything just works in the beginning, I recommend making everything public. I’ll write a post some other time to elaborate more on these.
The (return) type is used on methods, properties and classes. On a class, the type is simply “class”, and on an interface it will be “interface”.
On members, such as properties and methods, you’ll find lots of different types. for example:
public void Method();
is a method definition with a “void” return type, meaning it returns nothing.
public string GiveMeAString(int number);
is a method definition that takes an integer called “number” as a parameter, and returns a string.
You’ll find the same is true for properties.
public string myString;
is a property (or field*) definition in a class, stating that the property called “myString” is of type string.
* You’ll notice I used property and field interchangeably here, they are not the same. A property is actually a method that is accessed as if it was a field, they look alike. I used the word property here, because it is more easily understandable.
One last thing you’ll often find at the top of the file, above the namespace and class, are the using statements. These statements list the other namespaces that your code might depend on.
example:
Using System;
With this using statement, your code blocks can handle everything that is publicly available in the “System” namespace. Any part of your code that would want to use the dog or cat class, will need
to include the “Animals.Mammals” namespace like so:
Using Animals.Mammals;
So to sum this up, I’ll write a small class in the next section to give an example.
What is a class?
I have talked a bit about structure, classes, namespaces and methods already, but haven’t yet explained what these are.
Classes are a way that we structure our code, similar to namespaces. Think of a class like a template,
or a blueprint. It’s a description of an object without the specifics about that particular object.
A namespace can be compared to a folder, or a subdivision in your structure that allows you to categorize your code and makes it easier to read and find your way through complex architectures.
Let’s think of an example, think of a dog, any dog.
In my mind, I’m thinking of a tiny brown chihuahua. I hate chihuahua’s, but it’ll do the trick.
Now there’s a difference between this specific chihuahua and the generic “dog” I asked you to think about. The dog in this case would be the class, and the chihuahua, would be a specific instance of that class, or an object.
The class “Dog”, would have several properties, like color, breed, and size. This is the template for the chihuahua, where all these properties get a specific value, and the “dog” template, or blueprint, becomes a concrete object (or animal).
As I explained earlier, namespaces let us structure our codebase. For example:
Animals.Mammals.Dog;
From this namespace, we can see that the Dog belongs to the Mammals, which in turn belongs to the Animals.
I’ll show a quick example of how this would look in code:
namespace Animals.Mammals{
public class Dog{
public string Breed;
public float Size;
public Color Fur;
}
}
It’s that simple, and elsewhere in the code, you might find a specific instance of this dog being created like so:
var myDog = new Dog() { Breed = “chihuahua”, Size = 0,2f, Fur = Color.Brown }
Now, myDog is an object, a specific instance of the class Dog.
In this example, I chose not to use the constructor to pass the property values to, because it’s not really that relevant in this context to explain what exactly a constructor is. Think of a constructor as a method that returns an object of the type it’s defined in, you could pass the property values between the ( and ) brackets.
What are properties and variables?
Now that I’ve explained what a class is, It’ll be a bit easier to show what properties and variables are.
The easiest way to think of it is like this: What is the color of your car?
Whatever the answer is, we can agree that this color, is a property of your car. So if I would ask the same question about myDog, I can write it in code like this:
myDog.Fur;
So a property is an attribute, or a feature that characterizes a class.
It’s easy to confuse a property with the concept of a variable. A variable is something similar, but doesn’t necessarily belong to a class. A variable is something you’ll find in a method, and is subject to change, but it may be defined in that method, or it could be passed to that method via a parameter.
What is a method?
Simply put, a method is a function, a chunk of code that you can reuse. In object oriented programming, functions are found inside classes. So when you have an instance of this class, you can call that function on it.
For example, let’s give our dog a new method:
namespace Animals.Mammals{
public class Dog{
public string Breed;
public float Size;
public Color Fur;
public void Walk(){
Console.WriteLine(“walking”);
}
}
}
You can see I added the method walk. So now, I can continue on the code I wrote earlier:
var myDog = new Dog() { Breed = “chihuahua”, Size = 0,2f, Fur = Color.Brown }
myDog.Walk();
Note that I can only call this method if I first created an instance, because it is not a static class.
Calling a method on a class that has not been instantiated, will not compile.
If you would like to learn more about static classes, let me know and I’ll write a post about it another time. For now, let’s only focus on objects.
Whenever I call the Walk method, it will print “walking” to the console. Of course you can make it do whatever you want, this is just for illustration purposes. But let’s change it up a bit and add a parameter:
public void Walk(float distance){
Console.WriteLine(“walking ” + distance + “ km,”);
}
Now, Walk takes a parameter, in the form of a floating point number. This floating point number is a variable called distance.
Note that if I now call
myDog.Walk(1f);
It will print:
walking 1km.
Inheritance
In Object Oriented Programming, there are 4 pillars:
- Encapsulation
- Abstraction
- Polymorphism
- Inheritance
I won’t go into each pillar into depth, and have actually already explained a little bit about encapsulation when talking about the properties and methods.
What’s important here is that you understand the underlying concepts, without diving too much into the theory.
When I say inheritance, I mean that a characteristic of a class is derived from another class. For example: The Dog has a method called Walk, but this is a function that a lot of mammals have.
So why not create a class called Mammal, like this:
public class Mammal{
public void Walk(float distance){
Console.WriteLine(“walking ” + distance + “ km,”);
}
}
and now, let’s remove that same method from our Dog, and change the class so it looks like this:
public class Dog: Mammal {
public string Breed;
public float Size;
public Color Fur;
}
Now, my chihuaha can still walk, because it “inherits” that behaviour from the class Mammal, but I can reuse that for every other mammal, like cats, elephants, etc… There’s no need to reintroduce this behaviour each time. On top of that, if I want to override it on one class, I can just mark it as virtual, and override in the inheriting class like so:
public class Mammal{
public virtual void Walk(float distance){
Console.WriteLine(“walking ” + distance + “ km,”);
}
}
public class Cat: Mammal {
public override void Walk(float distance){
Console.WriteLine(“The cat is lazy and is sleeping…”);
}
}
now when I do this:
var myCat = new Cat();
myCat.Walk(1f);
It will print:
The cat is lazy and is sleeping…
Both cat and dog classes now have this behaviour, but the dog inherits the same behaviour as the Mammal class, while the cat overrides it.
Boxing and unboxing
Another of the pillars of OOP is called “PolyMorphism”, which rougly translates to “many-shaped”.
What this basically comes down to, is that objects of a derived class, can be treated as objects of the base class.
For instance, I can do something like this:
Mammal myDog = new Dog() { Breed = “chihuahua”, Size = 0,2f, Fur = Color.Brown }
Mammal myCat = new Cat();
both will work, and on both I can call the Walk method with different outcomes. But both variables myDog and myCat are now boxed. At runtime, we don’t exactly know what class they are an instance of, only that both are derived from Mammal.
If we would like to know exactly, then we can unbox them in several ways.
We can do a cast, like this for example:
(Dog)myDog;
or
myCat as Cat;
or we could do a check (which is probably the safest way to do it)
if(myDog is Dog unboxedDog) {
unboxedDog.Fur = Color.Black;
}
Abstraction and interfaces
Very similarly, I have given examples of abstraction and interfaces indirectly in previous examples, but I’ll address those concepts specifically in this section.
Whenever I refer to the Dog or Cat instances as a Mammal, I’m actually treating those instances in a more abstract manner, since a mammal is less concrete than a dog or a cat. i.e. everybody knows what a dog or a cat is, but try to imagine a mammal without thinking of a specific animal. That’s what’s meant by “abstraction”.
To give another example of this, think about the users of your application. Every user of your application is a person, but sometimes you’ll have a class called “Customer”, sometimes it’ll be “User”, “Supplier”, etc… Each of those classes is an extension of the abstract “Person”, but not every one of them is treated in the same way. Sure, all of them have a name, date of birth, address… which could all be attributed to the abstract “Person”, but the “Customer” doesn’t have the ability to supply you with goods.
Now that abstraction is a bit clearer, let’s look at this thing called “interfaces”.
Think of an interface as a contract, it says something about what you can do with an instance of a class. But an interface is not like a class, it doesn’t have code blocks, it only describes functions. Remember the Walk method we had on Mammals earlier? That actually applies to every animal with legs, no? So instead of attributing that method to the Mammals, let’s create an interface for it, named “Iwalkable
“. It would look something like this:
public interface Iwalkable {
void Walk(float distance);
}
There are a few things to note here:
Firstly, the Walk method does not have a any modifiers. This is because an interface is a contract for
what you can do with the class. So anything listed in this interface, must be a member of the inheriting
class. Thus interface members are public by default.
Secondly, the method doesn’t have a body. This is important because it only gives you an idea of what you can do with any class that implements Iwalkable
, so let’s let Mammal implement Iwalkable
:
public class Mammal: Iwalkable {
void Iwalkable.Walk(float distance){
Console.WriteLine("walking " + distance + "km");
}
}
Whenever we now have an instance of say a dog:
var myDog = new Dog();
We can see that it implements that interface, because Dog inherits from Mammal, and Mammal implements IWalkable:
if(myDog is Iwalkable walkable) {
walkable.Walk(1f);
}
But why would we do this, wouldn’t it be easier to just add the methods to the objects themselves, and just check the type itself?
Sure, you could absolutely do this, but that would require a whole lot of checks and for each class, you would need to update a bunch more things. So let me explain with another example
public interface Isteerable {
void Steer ();
}
public class Vehicle : Isteerable
{
void ISteerable.Steer(){
Console.WriteLine("steering...");
}
}
If you’re building a game, for example, you might come across the situation, that allows you to drive a vehicle. But whatever vehicle that is, you don’t want to check if it’s a bicycle, a car or an airplane, you just want to steer it, or turn on the radio, or honk the horn. So we don’t want to build our code like this:
if (vehicle is Car car){
car.TurnSteeringWheel();
}
else if (vehicle is Bike bike){
bike.TurnHandleBar();
}
instead, you would do this:
If (vehicle is Isteerable steerable) {
steerable.Steer();
}
There’s no need to unbox every class into all specific classes that might have similar functionality. Besides that, it’s possible that each class implements it differently, and you would still end up with convoluted spaghetti code. Instead, a simple small contract like an interface allows you to use an object in a standardized way, and abstractions allow you to override behaviour if needed.
There is a lot more explaining to do when it comes to Object Oriented Programming, and C#, but I hope that with this explanation, I have at least cleared up some things. Feel free to let me know in the comments what you would like to know more about, and I’ll go through them to find inspiration for a next post.