OOP - Program Integrity

One of the purposes of encapsulation is to keep the data secure, not just by restricted access to data, but also by preventing actions that could set the attributes to an invalid state.

Access Modifiers

Consider the Bank Account program we were developing last lesson.

We created:

  • private fields to store the data for an object.

  • public properties to get and set the state of the fields.

  • a public method to return data (that combined and formatted data from multiple fields).

Encapsulation allows us to bind together data and methods together in one object. Doing this allows us to protect the data it holds by limiting the interactions a user of the class can have using the public and private access modifiers (or flags).

The public modifier (+) permits a member of a class to be accessed from outside of the class.

The private modifier (-) restricts a member of a class so that it can only be accessed by code within its own class.

If you do not provide an access modifier when defining attributes or methods, C# implicitly treats them as private. However it is good practice to explicitly state they are private for clarity.

Demo

  • Adding the Balance Property

  • Validating a Deposit

Code from Demo

class BankAccount

{

//Define attributes

private string surname; //field

private string firstName;

private double balance;


public string Surname //property

{

get { return surname; } //get method

set { this.surname = value; } //set method

}


public string FirstName //property

{

get { return firstName; } //get method

set { this.firstName = value; } //set method

}


public double Balance

{

get { return balance; }

}


//Define Constructors


//Define Methods

public string GetSummary()

{

string summary = this.surname + ", " + this.firstName + " - £" + this.balance;

return summary;

}


public bool CreditBalance(double amount)

{

bool validTransaction = false;


if (amount >= 0)

{

validTransaction = true;

this.balance += amount;

}

return validTransaction;

}

}


class MainClass

{

public static void Main(string[] args)

{

string theSurname;

string theFirstName;

double openAmount;

//instantiate an object:

BankAccount myAccount = new BankAccount(); //call the constructor


Console.WriteLine("Bank Account Demo\n");


//The UI - ask for the surname

Console.Write("Enter surname: ");

theSurname = Console.ReadLine();

Console.Write("Enter first name: ");

theFirstName = Console.ReadLine();

Console.Write("Enter the initial deposit: ");

while (!double.TryParse(Console.ReadLine(), out openAmount) || !myAccount.CreditBalance(openAmount))

{

Console.Beep();

Console.WriteLine("Invalid amount");

Console.Write("Enter the initial deposit: ");

}


//Assign data to object

myAccount.Surname = theSurname;

myAccount.FirstName = theFirstName;


//Get data from object

Console.WriteLine("The name for this account is {0}, {1}", myAccount.Surname, myAccount.FirstName);

Console.WriteLine("The opening balance is £{0}", myAccount.Balance);

}

}

Challenge

Extend the demo by adding:

  • A public method - DebitBalance(double amount)

  • Modifications to the UI (in Main) so that after displaying the opening balance, it gives the user an option to debit or credit the account.

Program Integrity

What happens if a user tried to take from the account an amount larger than the balance?

Thanks to encapsulation our methods are bound together with the data, so we can protect our data, not just from external access but from invalid actions – e.g. taking an account into a negative balance.

Demo

  • Adapt DebitBalance method so that it returns true or false if it was able to debit the account.

  • Adapt the main so the UI informs the user if it was unable to carry out the transaction.

Code from Demo

Code from BankAccount Class

public bool DebitBalance(double amount)

{

bool validTransaction = false;


if (this.balance >= amount)

{

validTransaction = true;

this.balance -= amount;

}

return validTransaction;

}

Code from Main

Console.Write("Enter amount to withdraw: ");

while (!double.TryParse(Console.ReadLine(), out tempAmount) || tempAmount < 0)

{

Console.Beep();

Console.WriteLine("Invalid amount");

Console.Write("Enter withdrawal amount: ");

}

if (myAccount.DebitBalance(tempAmount))

{

Console.WriteLine("Amount successfully withdrawn");

Console.WriteLine("The current balance is £{0}", myAccount.GetBalance());

}

else

{

Console.Beep();

Console.WriteLine("Transaction incomplete. Insufficient funds.");

Console.WriteLine("The current balance is £{0}", myAccount.GetBalance());

}