| [ directory ] |
|
4.1 Object CreationThe cornerstone of any object-oriented programming language is the concept of an object. An object is a data structure that has methods and fields. Fields maintain the state of the object, and methods query or modify that state. Objects provide a convenient container for storing data. The number and type of lids on that container dictate the access control to the data. For example, an object that has only public methods is like an open container. Objects can get heavy (consume more memory) depending on the data they store. Objects are also used for abstracting the relationships among data. In OOP languages such as C++, Java, and C#, objects are created using the new operator. An object is created in memory (usually the heap), and a reference to that object is obtained as shown here: object o = new object(); The left side has the reference o, and it is assigned to the newly created object on the right side. Note that the reference o is merely a pointer to the actual object on the heap. You can use the reference to modify and query the state or data of the actual object by calling the object's method or setting its field: o.field = "c#" o.sayHello(); When you null an object, you merely set its reference to null. The keyword null is used in C++, Java, and C# to null objects. Note that null is not an object. Instead, it is a standardized reference to which references such as o can be set in order to null objects. Therefore, the following statement merely makes the reference o point to the null reference: o = null; After the reference is set to null, calling a method or accessing a field on that reference will give the classic NullPointerException (Java). This is obvious because there is no underlying object to which this reference is now pointing. Note that a reference is a façade used to manipulate the actual object. References can be assigned to each other. Therefore, the following statement will assign an additional reference o1 to the object created earlier: object o1 = o; Assigning null to the reference o will not affect the reference o1. This latter reference will still keep pointing toward the actual object. When there are no such pointers (references) to that object, the object in memory is considered garbage, and the garbage collector (if one is supported by the language) will free up the memory consumed by that object. In C# and Java, automatic garbage collection takes care of deallocating memory that was allocated using the new operator. Because object destruction is no longer an issue, programmers can now focus on proper class design and efficient object creation, thereby simplifying OOP. Still, you do need some knowledge of memory management and garbage collection to avoid mistakes that would hamper the garbage collection process. Section 4.8 discusses these issues in more detail. 4.1.1 The C# Equivalent of java.lang.ObjectBoth Java and C# have single-root object hierarchies. All objects always extend a standard root class. In Java this is the java.lang.Object class, and in C# it is the System.Object class. Table 4.1 compares System.Object and java.lang.Object and their approximate method equivalents. If you are confused as to why the C# System.Object is referred to as object, it's because object is an alias for System.Object. To illustrate the various methods of System.Object, let's create a sample object as shown in Listing 4.1.
Listing 4.1 Sample Object (C#)
using System;
public class Person {
string name;
public Person (string name) {
this.name = name;
}
public override string ToString() {
return this.name;
}
public override int GetHashCode() {
return this.name.GetHashCode();
}
public override bool Equals(object o) {
if (o != null && o.GetType().Equals(GetType())) {
return this.name.Equals(((Person)o).name);
}
return false;
}
public Person copy() {
return (Person)this.MemberwiseClone();
}
}
Listing 4.2 runs some tests on the Person object. Listing 4.2 Testing Person Objects (C#)
using System;
public class Test {
public static void Main(string[] args) {
Person p1 = new Person("chris");
Person p2 = new Person("chris");
Person p3 = p1;
//Comparing p2 and p1;
Console.WriteLine("Comparing p1 and p2");
Console.WriteLine (p1.Equals(p2));
Console.WriteLine (p1 == p2);
Console.WriteLine (Person.ReferenceEquals(p1, p2));
//Comparing p3 and p1;
Console.WriteLine("Comparing p1 and p3");
Console.WriteLine (p1.Equals(p3));
Console.WriteLine (p1 == p3);
Console.WriteLine (Person.ReferenceEquals(p1, p3));
//Comparing p4 and p1;
Console.WriteLine("Comparing p1 and p4");
Person p4 = p1.copy();
Console.WriteLine (p1.Equals(p4));
Console.WriteLine (p1 == p4);
Console.WriteLine (Person. ReferenceEquals (p1, p4));
//Miscellaneous object methods
Console.WriteLine(p1.GetType());
Console.WriteLine(p1.ToString());
Console.WriteLine(p1.GetHashCode());
}
}
The output of Listing 4.2 is as follows: Comparing p1 and p2 True False False Comparing p1 and p3 True True True Comparing p1 and p4 True False False Miscellaneous object methods Person chris 177073830 The output will be obvious to most Java programmers because it is in tune with Java's notion of equality of objects. The following are the common ways to check for equality of objects:
Note that in the Person class we created a copy() method that wraps the protected MemberwiseClone method. MemberwiseClone() is a protected method of the Object class that creates a shallow copy of the object. The method creates a new object in memory, and hence the == operator and the ReferenceEquals method return false for equality. The other methods of the System.Object class are similar in nature to those of the java.lang.Object class. The next section explores writing C# classes. |
| [ directory ] |
|