Working with Classes

Note: The following tutorial utilizes Java to show classes. While C++ and C# have some syntax differences, the concepts are very similar.

For object oriented programming, the files created to run a series of instructions are known as classes. Contained within this file would be constructors that create object methods for a class, object methods that can be used by object variables from a class which are usually called getters and accessors, and in many cases, but not always a main method that is ran when the file is executed. It is through utilizing a class to handle different capabilities that we are able to handle information that requires more than one primitive variable to handle it. Now, before I continue I will briefly cover the main method, which is the most commonly used method in a class when initially learning how to program. An example of the main method in use can be seen below.

public class whaddupBitches{
//Whaddup Bitches: The class used by Amp cause he doesn't like Hello World!
        public static void main(String[] args){
                System.out.println("Whaddup Bitches!");
        }
}

When this class is compiled and executed, this program will print to the console "Whaddup Bitches!" The main method is the method executed when a class is ran. Not all classes make use of the main method though as some don't need it. Something I will point out is that all of the programming examples that I have used to date in this series of guides can actually be implemented in a main method in a heartbeat. With that in mind, I encourage those not familar with the main method to experiment around with this.

Now that I have covered the main method, I wish to cover one of the reasons that a class is so powerful, which is its constructors. This allows for the creation of an object variable of a class, which from that point can be utilized by various methods. When making a class to handle bank accounts, chances are class variables will be used to handle the name of the person who the account belongs to, the account number, and the balance of the account. An example of this can be seen below:

public class bankAccount{
        private int accountNum;
        private String accountName;
        private double accountBal;
// remaining code omitted...
}

In the first part of this class, I have created the bankAccount class by declaring if it is a public or private, then declaring that it is a class. Some classes can be made private when created inside of another class, but that will not be covered in this part of the guide. From here, I declare the three class level variables accountNum, accountName, and accountBal. Note that I have made all three of these variables private so that only methods within the bankAccount class can access these variables. Now, obviously this is far from the only thing required for this class, as in order to utilize a class object, a constructor is necessary. The following example creates a constructor that gets input for the class variables:

public bankAccount(int accountNum, String accountName, double accountBal){
        this.accountNum = accountNum;
        this.accountName = accountName;
        this.accountBal = accountBal;
}

In this example, I use the same name for the input received by the constructor. This is actually allowed as the class variables are shadowed by the constructor. (This also applies to methods.) To access the class variables, I use the 'this' keyword which allows me to access the variable within a current object. As a result, the input received in the bankAccount constructor is used to initialize the three class variables within the bankAccount class. One important thing to know about constructors is that multiple constructors can actually be created in a class as long as they do not use the same input fields. Doing this is usually called 'constructor overloading.' (This can also be used with methods.) For example, I can also make a bankAccount constructor that takes the account number and account name, but not the balance as seen below:

public bankAccount(int accountNum, String accountName){
        this.accountNum = accountNum;
        this.accountName = accountName;
}

Constructors could also be made that will only take an account number, an account name, or even nothing as input but in some cases doing this would be impractical. When using arrays to declare a object variable based on the bankAccount class though, having a constructor that doesn't initialize any variables can be very useful. It is up to the individual creating the class to determine what constructors are necessary for the task they wish to carry out.

In order to utilize a constructor, an object variable must be declared that utilizes it. An example showing the creation of an object variable from the bankAccount class is shown below:

bankAccount newAccount = new bankAccount(1, "Dr. Evil", 1000000.00);

Notice that the variable type is bankAccount and that unlike a primitive variable, I state within the account to create a new object variable from the bankAccount class in the second half. The values within 'new bankAccount' indicates what constructor to use if multiple constructors are used. For example, when I create this variable, I call forth the bankAccount constructor which takes input for integer, String, and double variables in that order. It is important that the order given for the values is important as having them in the wrong order can cause an error when dealing with different primitive variable types.

Once an object variable is created that uses the bankAccount class, we have to be able to utilize the values within the variable. With that in mind there are two method types that are utilized to do this called getters and setters. Getters are usually used just to obtain one of the values held in the object variable. Setters are used to change one of the values held in the object variable. An example of a getter is shown which retrieves the balance of an account.

public double getBalance(){
        return this.accountBal;
}

In this example, I create a public method called getBalance which returns a double value. This method can be be stored in another variable, or within a print statement. For example, here's a main method that creates object variable called exampleAccount from the bankAccount class and uses the getBalance method within a print statement to print the balance to a console.

public static void main(String[] args){
        bankAccount exampleAccount = new bankAccount(12345, "Dark Helmet", 20.01);
        System.out.println("The balance for this account is $" + exampleAccount.getBalance() + ".");
}

In the example I have given, the values stored in object variable exampleAccount has the account number as "12345", the account name as "Dark Helmet", and the account balance as "20.01." In the print statement I use, the line "The balance for this account is $20.01." is printed to the console. Being able to change the account balance as necessary is also necessary though for this program to be practical, so a accessor that can change the balance as necessary should be created. In the following example provided, the method 'balanceWithdraw' withdraws money from an account if it has enough money in the account so that the transaction can be made and returns a boolean of true. If it cannot do so, then a boolean value of false is returned.

public boolean withdraw(double amt){
        // using code tag instead of java tag cause the Java tag doesn't handle zero correctly
        if (this.accountBal - amt >= 0){
                this.accountBal = this.accountBal - amt;
                return true;
        } else{
                return false;
        }
}

In the next example, I show the changeBalance accessor in use via a main method:

public static void main(String[] args){
        bankAccount exampleAccount = new bankAccount(12345, "Dark Helmet", 20.01);
        System.out.println("The balance for this account is $" + exampleAccount.getBalance() + ".");
        boolean check = exampleAccount.withdraw(20.00);
        if (check){
        System.out.println("Transaction successful:  Account balance is $" + exampleAccount.getBalance() + ".");
        }
        else{
        System.out.println("There isn't enough money in the account for this transaction to be completed.")
        }
}

In the example I just gave, the transaction I carried out was a withdraw of twenty dollars and the account had twenty dollars and one cent. Cause of this, the transaction would be successful and would print a statement to reflect its success. Has there of been less than twenty dollars in the account, the transaction would not be successful and would return a message to reflect it. Now, this is a very simplistic way to show such a method as the print statement can be handled within the accessor itself should the user wish to. It is mainly up to how the individual creating the program wants to handle it.

Now, I will mention that getters and accessors can be made to handle all primitive variables within the bankAccount object. For example, the account number and the account name can be accessed or changed. However, for some cases making an accessor is not necessary for some information that should not be changed such as the account number. With this in mind, I wish to close out this part of the guide with an example covering how a fully functional bankAccount class would be used.

public class bankAccount{
        private int accountNum;
        private String accountName;
        private double accountBal;
       
        //There are three constructors for this class as seen below.
        public bankAccount(int accountNum, String accountName, double accountBal){
                this.accountNum = accountNum;
                this.accountName = accountName;
                this.accountBal = accountBal;
        }
       
        public bankAccount(int accountNum, String accountName){
                this.accountNum = accountNum;
                this.accountName = accountName;
                //When no account balance is given, this constructor assumes that the account has no money.
                this.accountBal = 0.00;
        }
       
        //This constructor can be used for arrays should they be necessary.
        public bankAccount(){
        }
       
        //The following three methods are getters for the bankAccount class.
        public int getAccountNum(){
                return this.accountNum;
        }
       
        public String getAccountName(){
                return this.accountName();
        }
       
        public double getBalance(){
                return this.accountBal;
        }
       
        //The next three methods are accessors for the bankAccount class.  Note that I have opted not to
        //have an accessor for the account number.
        public boolean withdraw(double amt){   
        // using code tag instead of java tag cause the Java tag doesn't handle zero correctly
        if (this.accountBal - amt >= 0){
                        this.accountBal = this.accountBal - amt;
                        System.out.println("Withdraw successful:  Balance is $" + this.accountBal);
                        return true;
                }
                else{
                        System.out.println("Withdraw unsuccessful:  Not enough money in this account.");
                        return false;
                }
        }
       
        public void deposit(double amt){
                this.accountBal = this.accountBal + amt;
                System.out.println("Balance is now $" + this.accountBal);
        }
       
        public void changeName(String newName){
                this.accountName = newName;
        }
       
        //Last, but not least is the main method.
        public static void main(String[] args){
                bankAccount exampleAccount = new bankAccount(12345, "Dark Helmet", 20.01);
                System.out.println("The balance for " + exampleAccount.getAccountName() +"'s account is $"
                                + exampleAccount.getBalance() + ".");
                exampleAccount.changeName("Rick Moranis");
                exampleAccount.deposit(1000);
                System.out.println("The balance for " + exampleAccount.getAccountName() +"'s account is $"
                                + exampleAccount.getBalance() + ".");          
        }
}

Now I will mention that I did not follow the java coding conventions for this class as this is mainly a proof of concept and would require me to fully javadoc the entire class. I do recommend following coding conventions for the programming language being used at all times as it will improve code readability.

August 9th Append:

After utilizing C++ for various projects, I have opted to talk about how classes work for that language as well. Now, the concepts will essentially be the same as seen in Java. What makes it rather different however is that you can define the class using a header file and make a .cpp file of the same name as that header which holds all information for the functions. As such, I have opted to make a header of BankAccount.h which has all details about how the more detailed methods and constructors work stores in BankAccount.cpp and these are utilized in turn by Main.cpp. Below I have shown the examples of each file.

First, here's how BankAccount.h works:

//
//  BankAccount.h
//  proofofconcept
//
//  Created by Amp on 8/9/13.
//  Copyright (c) 2013 Amp. All rights reserved.
//

#ifndef BANKACCOUNT_H
#define BANKACCOUNT_H

#include <string>

using namespace std;

class BankAccount {

private:
    int accountNum;
    string accountName;
    double accountBal;

public:
    //Constructors defined here
    BankAccount(int accountNum, string accountName ,double accountBal);
    BankAccount(int accountNum, string accountName);
    BankAccount() {}

    //Accessor Methods
    int getAccountNum() { return accountNum; }
    string getAccountName() { return accountName; }
    double getAccountBal() { return accountBal; }
   
    //Mutator Methods
    bool withdraw(double amt);
    void deposit(double amt);
    void changeName(string name);
};

#endif

Now, here's how BankAccount.cpp works:

//
//  BankAccount.cpp
//  proofofconcept
//
//  Created by Amp on 8/9/13.
//  Copyright (c) 2013 Amp. All rights reserved.
//

#include "BankAccount.h"
#include <iostream>

using namespace std;

// Constructors

BankAccount::BankAccount(int accountNum, string accountName, double accountBal){
    this->accountNum = accountNum;
    this->accountName = accountName;
    this->accountBal = accountBal;
}

BankAccount::BankAccount(int accountNum, string accountName){
    this->accountNum = accountNum;
    this->accountName = accountName;
}

bool BankAccount::withdraw(double amt){
    if (this->accountBal - amt >= ){
        this->accountBal = this->accountBal - amt;
        cout << "Withdraw successful:  Balance is $" << this->accountBal << "\n";
        return true;
    }
    else{
        cout << "Withdraw unsuccessful:  Not enough money in this account.\n";
        return false;
    }
}

void BankAccount::deposit(double amt){
    this->accountBal = this->accountBal + amt;
    cout << "Balance is now $" << this->accountBal << "\n";
}

void BankAccount::changeName(string name){
    this->accountName = name;
}

Last, but not least, here's Main.cpp

//
//  main.cpp
//  proofofconcept
//
//  Created by Amp on 8/9/13.
//  Copyright (c) 2013 Amp. All rights reserved.
//

#include "BankAccount.h"
#include <iostream>

using namespace std;

int main(int argc, const char * argv[]) {
    BankAccount *example = new BankAccount(12345, "Dark Helmet", 20.01);
    cout << "The balance for " << example->getAccountName() << "'s account is $"
        << example->getAccountBal() << ".\n";
    example->changeName("Rick Moranis");
    example->deposit(1000);
    cout << "The balance for " << example->getAccountName() << "'s account is $"
        << example->getAccountBal() << ".\n";
    delete example;
}

On BankAccount.h allow me to mention that I have the lines #ifndef and #define in there that mention the file itself. These are called include guards and prevent a header from being defined twice in a project. If I did not have this in, I would have had a compilation error and when using header files it is recommended to do this as a precaution. In addition, it can be seen that once I am done it with, I used the delete operator on the example variable to free up the memory. For more information on this, I would suggest reading the Memory Management portion of this tutorial. There are plenty of other ways that classes can be utilized in programming, but it is mainly up to what the class is needed for in a project. With that in mind, I suggest experimenting with this in different types of projects.