Difference between revisions of "An Overview of Objective-C Object Oriented Programming"

From Techotopia
Jump to: navigation, search
(Declaring an Objective-C Class Implementation)
(Declaring, Initializing and Releasing a Class instance)
Line 156: Line 156:
 
<pre>
 
<pre>
 
BankAccount *account1 = [[BankAccount alloc] init];
 
BankAccount *account1 = [[BankAccount alloc] init];
 +
</pre>
 +
 +
In the first step of this section we allocated memory for the creation of the class instance. Good programming conventions dictate that memory allocated to a class instance should be released when the instance is no longer required. Failure to do so can result in memory leaks and such that the application will continue to use up system memory until none is left. Those familiar with Java will be used to relying on the ''garbage collector'' to free up unused memory automatically. Objective-C has no such luxury and the memory allocated to a class instance must be manually released:
 +
 +
<pre>
 +
[account1 release]
 
</pre>
 
</pre>
  

Revision as of 20:24, 13 October 2009

So far in Objective-C Essentials we have looked at the basics of programming in Objective-C such as variable types, flow control and looping. Although it would be possible to write a functional program using these techniques, there is much more to becoming a proficient Objective-C programmer. Objective-C is, above all, an object oriented programming language and as such any Objective-C programmer will be expected to create object-oriented applications using this language.

Objective-C provides extensive support for developing object-oriented applications. The subject area of object oriented programming is, however, large. It is not an exaggeration to state that entire books have be dedicated to the subject. As such, a detailed overview of object oriented software development is beyond the scope of this book. Instead, we will introduce the basic concepts involved in object oriented programming and then move on to explaining the concept as it relates to Objective-C application development.


Contents


What is an Object?

<google>ADSDAQBOX_FLOW</google> An object is a self-contained piece of functionality that can be easily used, and re-used as the building blocks for a software application.

Objects consist of data variables and functions (called methods) that can be accessed and called on the object to perform tasks. These are collectively referred to as members.

What is a Class?

Much as a blueprint or architect's drawing defines what an item or a building will look like once it has been constructed, a class defines what an object will look like when it is created. It defines, for example, what the methods will do and what the member variables will be.


Declaring an Objective-C Class Implementation

Before an object can be instantiated we first need to define the class 'blueprint' for the object. In this chapter we will create a Bank Account class to demonstrate the basic concepts of Objective-C object oriented programming.

An Objective-C class is defined in terms of an interface and an implementation. In the interface section of the definition we specify the base class from which the new class is derived and also define the members and methods that the class will contain. The syntax for the implementation section of a class is as follows:

@interface NewClassName: ParentClass {

     ClassMembers;

}

ClassMethods; @end

The ClassMembers section of the implementation defines the variables that are to be contained within the class (also referred to as instance variables). These variables are declared in the same way that any other variable would declared in Objective-C.

The ClassMethods section defines the methods that are available to be called on the class. These are essentially functions specific to the class that perform a particular operation when called upon.

Methods come in two different forms, class methods and instance methods. Class methods operate at the level of the class, such as creating a new instance of a class. Instance methods, on the other hand, operate only on the instance of a class (for example performing an arithmetic operation on two instance variables and returning the result).

To create an example outline interface section for our BankAccount class, we would use the following:

@interface BankAccount: NSObject
{

}

@end

Now that we have the outline syntax for our class, the next step is to add some instance variables to it.

Adding Instance Variables to a Class

Instances of our BankAccount class will be required to store some data, specifically a bank account number and the balance currently held by the account. Instance variables are declared in the same way any other variables are declared in Objective-C. We can, therefore, add these variables as follows:

@interface BankAccount: NSObject
{
        double accountBalance;
        long accountNumber;
}

@end

Having defined our instance variables, we can now move on to defining the methods of the class.

Define Class Methods

The methods of a class are essentially code routines that can be called up to perform specific tasks.

Methods come in two different forms, class methods and instance methods. Class methods operate at the level of the class, such as creating a new instance of a class. Instance methods, on the other hand, operate only on the instance of a class (for example performing an arithmetic operation on two instance variables and returning the result). Class methods are preceded by a plus (+) sign in the declaration and instance methods are preceded by a minus (-) sign. If the method returns a result, the name of method must be preceded by the data type returned enclosed in parentheses. If a method does not return a result, then the must be declared as void. If data needs to be passed through the member (referred to as arguments, the member name is followed by a colon, the data type in parentheses and a name for the argument. For example, the declaration of a method to set the account number in our example might read as follows:

-(void) setAccountNumber: (long) y;

The method is an instance method so it is preceded by the minus sign. It does not return a result so it is declared as (void). It takes an argument (the account number) of type long so we follow the accountNumber name with a colon (:) specify the argument type (long) and give the argument a name (in this case we simply use y).

Methods may also be defined to accept more than one argument. For example to define a method that accepts both the account number and account balance we could declare it as follows:

-(void) setAccount: (long) y andBalance: (double) x;

Now that we have an understanding of the structure of method declarations within the context of the class interface definition, we can extend our BankAccount class accordingly:

@interface BankAccount: NSObject
{
        double accountBalance;
        long accountNumber;
}
-(void) setAccount: (long) y andBalance: (double) x;
-(void) setAccountBalance: (double) x;
-(void) setAccountNumber: (long) y;
-(void) displayAccountInfo;
@end

Having defined the interface, we can now move on to defining the implementation of our class.

Declaring an Objective-C Class Implementation

The next step in creating a new class in Objective-C is to write the code for the methods we have already declared. This is performed in the @implementation section of the class definition. An outline implementation is structured as follows:

@implementation NewClassName ClassMethods @end

In order to implement the methods we declared in the @interface section, therefore, we need to write the following:

@implementation BankAccount

-(void) setAccount: (long) y andBalance: (double) x;
{
        accountBalance = x;
        accountNumber = y;
}
-(void) setAccountBalance: (double) x
{
        accountBalance = x;
}

-(void) setAccountNumber: (long) y
{
        accountNumber = y;
}

-(void) displayAccountInfo
{
        NSLog (@"Account Number %i has a balance of %f", accountNumber, accountBalance);
}
@end

We are now at the point where we can write some code to work with our new BankAccount class.

Declaring, Initializing and Releasing a Class instance

So far all we have done is define the blueprint for our class. In order to do anything with this class, we need to create instances of it. The first step in this process is to declare a variable to store a pointer to the instance when it is created. We do this as follows:

BankAccount *account1;

Having created a variable to store a reference to the class instance, we can now initialize the class:

account1 = [BankAccount alloc];

In the above statement we are calling the alloc method of the BankAccount class (note that alloc is a class method as opposed to an instance method).

Having allocated memory for the class instance, the next step is to initialize the instance by calling the init instance method:

account1 = [account1 init];

For the sake of economy of typing, the above three statements are frquently rolled into a single line of code as follows:

BankAccount *account1 = [[BankAccount alloc] init];

In the first step of this section we allocated memory for the creation of the class instance. Good programming conventions dictate that memory allocated to a class instance should be released when the instance is no longer required. Failure to do so can result in memory leaks and such that the application will continue to use up system memory until none is left. Those familiar with Java will be used to relying on the garbage collector to free up unused memory automatically. Objective-C has no such luxury and the memory allocated to a class instance must be manually released:

[account1 release]

Calling Methods and Accessing Instance Data

A C# class is declared using the public class keywords followed by the name of the class. Although the C# compiler will accept just about any name for a class, programming convention dictates that a class name begin with a capital letter:

public class BankAccount
{

}

We have now defined a class which currently contains no members. The next task, therefore, is to add some members.

Creating C# Class Members

Class members or properties are essentially variables and methods embedded into the class. Members can be public, private or protected.

public members can be accessed from outside the object and are also visible in classes derived from the current class. private members can only be accessed by methods contained in the class and are not accessible to derived classes. protected classes are only available to derived classes.

This is the key to what is called data encapsulation. Object-oriented programming convention dictates that data should be encapsulated in the class and accessed and set only through the methods of the class (typically called getters and setters).

We can now extend our BankAccount class to add member variables to hold the account name and number. True to the concept of data encapsulation we will be making some of these members private and writing methods to access these values later:

public class BankAccount 
{

	public string accountName;
        public int accountFee;
	private int accountBalance;
	private int accountNumber;
}

Now that we have defined the properties of our class we need to look briefly at a few additional data member types, and then learn how to create object instances from the class.


Static, Read-only and Const Data Members

In addition the data member types we have looked at so far, C# also provides support for a number of additional member types.

C# static member types (also referred to as class properties) are used to store data values which are common to all object instances of class. For example, all bank customers would likely earn the same rate of interest on a savings account. An interestRate member would, therefore, be declared as static since it is common across all object instances of the class.

Static members are declared using the static keyword. For example:

public class BankAccount
{
       public static int interestRate;
}

Static members are accessed through the class, not though the object. For example we would change the interestRate member for all object instances by reference the BankAccount class as follows:

BankAccount.interestRate = 10;

For data members that must not be modified the const and readonly keywords are provided by C#. Both achieve the same objective of preventing the value assigned to a data member from being changed after it has been declared. The value of a const or readonly member must be assigned at creation time:

public readonly daysInWeek = 7;

Instantiating an Object from a C# Class

The process of creating an object from the class 'blueprint' is called instantiation. The first step is to create an object variable of the required object type. An instance of the object is then created using the new keyword and assigned to the object variable:

         BankAccount custAccount;

         custAccount = new BankAccount();

It is also possible to declare the object variable and assign the object in a single statement:

        BankAccount custAccount = new BankAccount();

Now that we have an instance of our BankAccount class the next step is learn how to access the members of the class.

Accessing C# Object Members

Now that we know how to write a class and instantiate objects from the class, we now need to know how to access the members of the object. Firstly, you will recall that we declared some members as being public and others as being private. The public methods are fully accessible from outside the object. This is achieved using something called dot notation. Dot notation is a mechanism by which object members may be accessed by specifying the object and member names separated by a dot (.). For example, to access the accountName member of an object named custAccount we would reference this member using custAccount.accountName:

using System;

class Hello
{
    public class BankAccount 
    {

	public string accountName;
        public int accountFee;
	private int accountBalance;
	private int accountNumber;
    }

        static void Main()
        {

		BankAccount custAccount = new BankAccount();

		custAccount.accountName = "John Smith";

		custAccount.accountFee = 5;

		Console.WriteLine ("Customer Name is " + custAccount.accountName);

		Console.WriteLine ("Account Fee = $" + custAccount.accountFee);
        }
}

The above code assigns values to the accountName and accountFee members of our object. It then references the properties in order to display text which reads:

Customer Name is John Smith
Account Fee = $5

This approach works well for public class members, but not for private members. An attempt, for example, to use dot notation to access the private accountNumber member will result in a compilation error along the the lines of:

error CS0122: 'Hello.BankAccount.accountNumber' is inaccessible due to its protection level

In order to access private members we need to provide access methods in the class.

Adding Methods to a C# Class

Class method members are sections of code contained in a class which can be called from outside an object to perform specific tasks. Common types of methods are getter and setter methods which are used to access private data members of a class. For example, we can declare a getter and a setter method to get and set the protected accountNumber member:

public class BankAccount 
{

	public string accountName;
        public int accountFee;
	private int accountBalance;
	private int accountNumber;

	public int getAccountNumber()
	{
		return accountNumber;
	}

	public void setAccountNumber(int newNumber)
	{
		accountNumber = newNumber;
	}

}

Class methods are called using dot notation. For example, to set the value of the accountNumber:

	BankAccount custAccount = new BankAccount();

	custAccount.setAccountNumber( 12345 );

	Console.WriteLine ("Account Number = " + custAccount.getAccountNumber() );

The above code sets the account number using the setter method and then displays the account number using the getter method.

Now that we have looked at method class members the next task is to look at two special class methods, constructors and finalizers.

C# Constructors and Finalizers

Despite the grand sounding names, C# class constructors and finalizers are nothing more than methods which get called when an object is instantiated and destroyed. The constructor is particularly useful for allowing initialization values to be passed through to an object at creation time. Let's say that we would like to be able to initialize the accountName and accountNumber members at the point that we initialize the custAccount object. To do so we need to declare a constructor.

Constructors are declared the same way as other methods with the exception that the name of the method must match the class name:

public class BankAccount 
{

	public string accountName;
        public int accountFee;
	private int accountBalance;
	private int accountNumber;

        // Constructor
	public BankAccount(string acctName, int acctNumber)
	{
		accountName = acctName;
		accountNumber = acctNumber;
        }

        // ....

}

We can now use the constructor to initialize these members at object creation:

	BankAccount custAccount = new BankAccount("Fred Wilson", 123456);

Finalizers are used to clean up any resources used by a class object when the object is destroyed. Unlike constructors which can be triggered from code using the new keyword there is no way to explicitly call a finalizer (for example there is no delete equivalent to the new keyword). Instead, the finalizer will be called when the garbage collector decides that the object instance is no longer needed. All the programmer can be sure of is that the finalizer will be called at some time between the when the object is no longer needed by the code and the point that the application terminates.

Finalizers are defined in the same way as constructors with the exception that the name is preceded by a tilde (~):

        // Finalizer
	public ~BankAccount(string acctName, int acctNumber)
	{
	      // Code to perform clean up
        }