Chapter 7: Classes.

sometimes, having simple variables to represent things can become, unmanageable or disorganized and we need something else.

as an example, imagine this.

int playerX = 0;
int playerY = 3;
int playerZ = 0;

that looks fine all things considered, but what if we have 2 players and not one.

int player1X = 0;
int player1Y = 3;
int player1Z = 0;
int player2X = 0;
int player2Y = 3;
int player1Z = 0;

like also sorta works, but imagine if we'll have 3, or 4, or who knows how many others. WE have the exact same variables for every player, we just need it to be stored differently.

this is where classes come in.

classes and members.

classes are custom types that you can create to store inside your custom variables. It's like how when a folder gets big enough you decide to split it into subfolders for it to be more manageable, classes are similar, and even more powerful than that.

let's look at an example of our player scenario.

public class Player
{
    public int x;
    public int y;
    public int z;
}

as you can see, class is a new statement, and we give it the name player.

the public keyword is called an access modifier, it basically tells the language who can access this code, class in this case, most of the time you just use public because other modifiers such as protected or internal are only useful in a library context and not an application one, more about this later.

Note, create a different file than Program.cs to put this, from now on, classes go into different files. This is because Program.cs can't handle classes with access modifiers.

then inside that class we have variables, those variables, unlike what we'll normally do, have no assign values. This is intentional.

classes aren't directly used, instead, you can think of a class as a template to use in a factory for something, then you ask the factory to create one and then you use it, and it exactly matchs the specifications you wrote in the class declaration.

remember Random? That's an example of a class that you are supposed to create. We create an instance with new.

instance is the programming term for the created class, and there can be more than one instance, there can be any number of instances for something, which is why they're handy in our problem from above.

let's see how.

Write this in Program.cs, since it's the code we want to run when the program is launched.

Player player1 = new Player
{
    x = 0,
    y = 3,
    z = 0
};
Player player2 = new Player
{
    x = 0,
    y = 5,
    z = 0
};
Console.WriteLine($"Player1: {player1.x}, {player1.y}, {player1.z}");
Console.WriteLine($"Player2: {player2.x}, {player2.y}, {player2.z}");

new is a keyword used to create a new instance of a class.

focus on the code, you see between every member of Player we assign we put a comma after it, that tells the compiler that we're not done yet, we will assign something else too. Except for the last one, because we assign nothing after that, so no need for a comma.

one thing you might be confused about is why did we put a semicolon at the end of the new block, this has a reason actually. Assignment always ends with a semicolon, and we assigned to a variable.

As you can see we accessed the variables inside the class instances with ., the same way we did when using WriteLine or ReadLine from the Console class.

But wait a second, why is this thing so different compared to Random?

There's a reason, we did not use a constructor, so we manually instanciate the class, but we can do it a cleaner way.

public class Player
{
    public int x;
    public int y;
    public int z;
    public Player(int x, int y, int z)
    {
        this.x = x;
        this.y = y;
        this.z = z;
    }
}

the public Player() part is the constructor, it's a special form of method that gets called when we do new(), and we can give it our arguments.

As you can see, when we have multiple arguments, we separate them with commas (,)

this basically says let's use this instance of Player, ordinarily we don't use this, but remember, there's both x y z above and x y z from the function, and the compiler is confused which one we want, so we do this.x for assignment, and we do = x to use the one from the function arguments. You can avoid this if you named the arguments something else.

public class  Player
{
    public int x;
    public int y;
    public int z;
    public Player(int newX, int newY, int newZ)
    {
        x = newX;
        y = newY;
        z = newZ;
    }
}

we don't use this here because there's no name ambiguity for the variables.

ok, so let's change our first creation of instances above with this new constructor style.

Player player1 = new(0, 3, 0);
Player player2 = new(0, 5, 0);
Console.WriteLine($"Player1: {player1.x}, {player1.y}, {player1.z}");
Console.WriteLine($"Player2: {player2.x}, {player2.y}, {player2.z}");

There, much shorter and easier to both read and write.

Next, methods.