|
Learning C# and OOP, Properties, Part 2Richard Baldwin illustrates reflection and introspection and explains why they are so important with respect to properties. Comparative information is provided for C# and Java. Published: October 29, 2002
C# Programming Notes # 106b
PrefaceThis lesson is part of a miniseries designed to teach you how to write object-oriented programs using C#. This is also the second part of a two-part lesson on C# properties. This miniseries will describe and discuss the necessary and significant aspects of object-oriented programming (OOP) using C#. The first lesson in the miniseries was entitled Learning C# and OOP: Getting Started, Objects and Encapsulation. The first part of this two-part lesson was entitled Learning C# and OOP, Properties, Part 1. Comparisons with Java The miniseries will also make comparisons between C# and Java with respect to both syntax and OOP concepts. I will emphasize the similarities between these two programming languages, which are likely to dominate the programming world in the foreseeable future. By studying these lessons and learning about OOP using C#, you will also be learning quite a lot about OOP using Java. Relatively high level I will provide the information in a high-level format, devoid of any prerequisite requirement to know C# syntax. In those cases where an understanding of C# syntax is required, I will provide the necessary syntax information in the form of sidebars and sample programs. Therefore, if you have a general understanding of computer programming, you should be able to read and understand the lessons in this miniseries, even if you don't have a background in object-oriented programming, or a background in the C# programming language. Viewing tip You may find it useful to open another copy of this lesson in a separate browser window. That will make it easier for you to scroll back and forth among the different listings while you are reading about them. Supplementary material I recommend that you also study the other lessons in my extensive collection of online programming tutorials. You will find a consolidated index of my online tutorials at www.DickBaldwin.com. PreviewSecond of two parts This is the second part of a two-part lesson that will concentrate on properties in C# and a comparison of C# properties with Java properties. A sample C# program is provided to illustrate C# properties. A sample Java program is also provided to illustrate the similarity of properties between C# and Java. Review of Part 1 In Part 1, you learned:
Except for reflection and introspection, part 1 also provided sample programs to illustrate the items in the above list. Reflection and introspection As stated above, the most important aspect of properties has to do with reflection and introspection. This is a process whereby one object can discover and manipulate the properties belonging to another unknown object even though the author of the executing program had no knowledge of the unknown object's class when the executing program was originally written. Reflection and introspection are discussed in detail in this lesson. Bound properties and constrained properties Another important characteristic of properties has to do with bound properties and constrained properties. This is a process by which an object can be automatically notified when the value of a bound or constrained property belonging to another object changes. A brief discussion of bound and constrained properties will also be provided in this lesson. Discussion and Sample CodeMy description of a property The following paragraphs review my description of a property from the first part of this lesson. This description is based on practical considerations. For the most part, I will describe the things that must be true for a property to exist, and more importantly, for the property to be really useful. Name, type, and value First, a property must have a name, a type, and a value, and possibly some other attributes as well, (such as being read only or read/write).
Same name and type, but different value A property belongs to an object. Every object instantiated from the same class will have the same set of properties. The properties belonging to all the objects instantiated from the same class will have the same names and types, but won't necessarily have the same values from one object to the next. Where is the value stored? The value of a property is probably most commonly stored in an instance variable belonging to the object, but that is not a requirement. The value could be stored in a database, or a disk file, or elsewhere, or could be computed on-the-fly when requested. The state of the object The value of a property generally contributes to the state of the object to which it belongs, and when the value of the property changes, the state of the object changes accordingly.
Standardization is required To be really useful, the access methodology for a property must be predefined and standardized within a given programming language. However, the access methodology need not be the same from one language to the next. The C# programming language accesses properties as fields, while the Java language accesses properties as methods. The most important aspect of properties It must be possible for executing code to learn everything there is to know about the properties belonging to an object at runtime, and to be able to access those properties for reading and writing at runtime.
For .NET, this capability must exist across several languages, even if the language used to define the class and its properties is different from the language used to instantiate objects from the class. A real-world example In the first part of this two-part lesson, I discussed the concept of developing software using software components, and how properties fit into that important field. I'll simply refer you to Part 1 of the lesson for a review of that material. What really matters is ... What really matters is that the mechanism for accessing properties must be predefined and standardized so that code can discover and manipulate the properties belonging to an unknown object at runtime. It's time to look at some code I'm going to show you a C# program that illustrates properties from three different viewpoints:
The first two viewpoints were covered in the first part of this two-part lesson. The third viewpoint is the primary topic of this part of the lesson. While you might find it complex, I hope that you will stick with it until you understand the concepts involved. A comparable Java program In addition, I'm going to show you a comparable Java program that accomplishes exactly the same thing as the C# program. I will compare the code between the two programs and discuss the similarities and the differences. You will see that even at the complex level of the third viewpoint, the concepts, and even the syntax in the C# program is very similar to the Java program. Explain in fragments The complete C# program is shown in Listing C9, and the complete Java program is shown in Listing J9. These two listings are near the end of the lesson. In order to help you to focus on important sections of code, I will explain the behavior of these programs in fragments. A target class The C# program consists of two classes. The first class, which I discussed in detail in Part 1, is named TargetClass. This class defines some properties (as well as some other members), which are accessed by code in the Main method of the other class named Props01. Listing C1 shows the entire definition of the class named TargetClass.
Of particular interest in this part of the lesson is the boldface material,
which defines two properties, named height and width.
An object of type TargetClass An object instantiated from the class named TargetClass contains:
The Main method Listing C2 shows the beginning of the class named Props01 and the beginning of the Main method in that class. This code begins by instantiating and saving a reference to a new object of the class named TargetClass discussed above. The reference is saved in the reference variable named obj. The reference to this object was used in Part 1 to access the public
instance variable, the hidden data, and the properties of this object.
The reference will be used in this part of the lesson, along with reflection, to discover
the properties belonging to the object at runtime.
The user viewpoint In this part, we will look at C# properties from the viewpoint of the sophisticated user who needs to first discover and then use properties at runtime. Three steps Basically, this process will consist of three steps. First I will get a reference to an object of the type Type, which represents the type of an object instantiated from the class named TargetClass. (This is similar to getting an object of the type Class in Java.) Next I will use the Type object to get an array of objects of type PropertyInfo. This array will contain one object for each property belonging to the target object of type TargetClass. (From the previous discussion, you already know that the target object contains two properties, one named height and the other named width. Therefore, the array will have two elements.) Finally I will iterate on the array object, using each object in the array to determine the name, type, and current value of the corresponding property belonging to the TargetClass object. C# and the Object class Listing C3 shows the first step in this process. (Note that
I skipped the code in the Main method that was covered in Part 1.)
All classes in C# (and Java as well) derive either directly or indirectly from the class named Object. The class named Object defines several methods that are inherited into all other classes. Some of those methods, (such as Equals and ToString), are meant to be overridden in new classes. They are declared to be virtual. The GetType method is not virtual Some of the methods, (such as GetType), are meant to be used as is, without overriding them. Those methods are not declared to be virtual, so they cannot be overridden. (Note that the GetType method in C# has the same purpose as the getClass method in Java.) A Type object When the GetType method is invoked on an existing object, it returns a reference to an object of the type Type. According to Microsoft,
Metadata vs. runtime type information In Java jargon, it would be said that the Type object exposes the runtime type information (RTTI) of the object on which the method is invoked (except that in Java the method is named getClass, and the object that is returned by the method is type Class instead of type Type).
Alternate ways to get a Type object There are several other ways to get a Type object as well, including the typeof operator and the static GetType method of the Type class (the GetType method invoked in Listing C3 is an instance method, defined in the Object class, and inherited into the TargetClass class). The GetType method The static GetType method of the Type class returns a Type object representing a type specified by the name of a class as a string. (The corresponding method in Java is the method named forName, which is a static method of the class named Class.) The typeof operator The typeof operator returns a Type object representing a type specified by the name of its operand. (This is similar, but not identical, to the instanceof operator in Java, which is used to determine the type of an object based on its reference.) What is a Type object? Here is what Microsoft has to say about a Type object:
Step 1: Getting the Type object The code in Listing C3 invokes the GetType method on the object instantiated earlier from the class named TargetClass. The GetType method returns a reference to an object of the type Type. This object represents the class from which the object was instantiated; TargetClass in this case. The reference to the Type object is saved in the reference variable named theType. Step 2: Getting property information In this step, we will get information about the properties defined in the class named TargetClass, which is represented by the object of the type Type. The Type class provides several methods that can be invoked on an object of the Type class, to get information about the type represented by the Type object. A few of those methods are shown in the following list to illustrate some of the information that is available. (In general, the names of the methods indicate the type of information that they are designed to provide.)
Invoking the GetProperties method The code in Listing C4 invokes the GetProperties method on the
Type
object.
According to Microsoft, the GetProperties method "Returns all the public properties of the current Type." The information is returned as an array of objects where each object in the array is of type PropertyInfo. One PropertyInfo object for each property Each object of type PropertyInfo in the array represents one of the properties belonging to the target object under investigation. In this case, the target object is the object instantiated from the class named TargetClass. Number of properties equals number of elements The number of elements in the array indicates the number of properties belonging to the target object. Using the Length property of the array Every array object in C# has a property named Length, whose value
is "The total number of elements in all the dimensions of the Array."
Since this is a one-dimensional array, the value of Length is the
same as the number of properties belonging to the target object.
The code in Listing C5 gets and displays the value of the Length
property.
The number of properties The code in Listing C5 produces the following output on the screen, which matches what we already know about the number of properties defined in the class named TargetClass. Number of Public Properties: 2 Getting information about each property Each of the PropertyInfo objects contained in the array can be
queried to obtain information about the specific property that it represents.
The code in Listing C6 displays some explanatory text on the screen and
then calls the method named DisplayPropertyInfo, passing a reference
to the array of PropertyInfo objects to the method.
The method named DisplayPropertyInfo is designed to get and display information from each element in the array. As a result, this method gets and displays information about each property in the class named TargetClass. PropertyInfo objects An object of the PropertyInfo type contains properties and methods that can be accessed to obtain information about the property that the object represents. For example, the name and the type of the property represented by the object are stored in the object's properties named Name and PropertyType. (Here we have the properties of one object represent attributes of a property of another object.) The DisplayPropertyInfo method The method named DisplayPropertyInfo receives a reference to
the array of PropertyInfo objects as an incoming parameter.
The entire method consists of a single for loop, and is shown in
Listing C7.
Step 3: Iterate on the array This method uses a for loop to iterate on the array, extracting name, type, and value information from each object stored in the array. Getting the name and type information is straightforward. Getting the value information is a little more complicated. (Listing C7 contains a comment separator to visually separate the code that gets the name and type from the code that gets the value.) Different issues From a conceptual viewpoint, there is a significant difference between name and type on one hand, and value on the other. The name and type of a property is the same for every object instantiated from a given class. However, the current value of the property will vary among different objects instantiated from the same class. Therefore, value is specific to each object instantiated from the class, while name and type are the same for all objects instantiated from the class. Getting the name and type The code to get and display the name and the type of the property represented by the PropertyInfo object is shown above the visual separator in Listing C7. As mentioned earlier, this code is straightforward. All that is required is to access the properties named Name and PropertyType belonging to the PropertyInfo object. The values of these properties are the name and the type of the property represented by the PropertyInfo object. Getting the property value for a specific object The code required to get and display the value of a particular property for a specific object is shown below the visual separator in Listing C7. This code consists of the following steps (as you will see later, despite its complexity, this is essentially the same process used to accomplish the same task in Java):
The MethodInfo class An object of the MethodInfo class represents a specific method. It contains numerous properties and methods that allow you to manipulate the method represented by the object. For example, there is a method named GetParameters that can be invoked to get a list that identifies the number and types of parameters required by the method. The Invoke method of the MethodInfo class In this case, we are interested in the Invoke method of the MethodInfo class. This method makes it possible for us to invoke the get method represented by the MethodInfo object on a specific object of the TargetClass class. The Invoke method requires two parameters. The first parameter is a reference to the object on which we want the get method to be invoked. In this case, this is the object of the class named TargetClass, which has been the target of the investigation from the beginning. The second parameter is a reference to an array object, where each element in the array contains a reference to an object that is to be passed as a parameter to the method being invoked. In this case, the get method requires no parameters, so the code in Listing C7 passes null as the second parameter to the Invoke method. Invoking the get method on the target object The result of invoking the Invoke method on the reference to the object of type MethodInfo, while passing the target object as a parameter, is to cause the get method to be invoked on the target object. The int value returned by the get method is picked up and returned by the Invoke method. This value is passed to the WriteLine method in Listing C7, which causes it to be displayed on the computer screen. The screen output The screen output for the first iteration of the for loop in Listing C7 is shown below: Name: height
This output indicates that the name of the first property found by our discovery process was height. This agrees with what we already know to be true. The property type information The property type reported by this process looks a little strange. What in the world is the type System.Int32? According to the documentation, the type System.Int32 represents a 32-bit signed integer. However, when we defined the class named TargetClass, we defined the type of the height property as type int, not type System.Int32. Here is what Microsoft has to say about the relationship between type int and type System.Int32, (with my parenthetical expression inserted):
Here is what Stanley Lippman has to say in C# Primer, A Practical Approach:
Thus, when we specified type int, we were actually using an alias to specify type System.Int32. The property value Finally, the current value represented by the height property on the target object is reported to be 20, which we can verify by examining Listing C9. The second property named width The screen output for the second and last iteration of the for loop in Listing C7 is shown below: Name: width
Because we defined the TargetClass, and wrote the program that defined the properties and set the values of the two properties, we know these to be the correct name, type, and current value. However, prior knowledge of the answers is not a prerequisite for the correct operation of this discovery process. It would work correctly if someone else had written the class named TargetClass and had provided us with only the compiled version of the class. An alternative approach for getting the property value The code in Listing C8 uses the GetValue method of the PropertyInfo
class to get and display the current property value. This single
statement is, in effect, a shorthand replacement for the last two statements
inside the for loop in Listing C7.
The importance of properties So now you know the true importance of properties in C#. In my opinion, the importance of properties has nothing to do with making properties look like fields instead of methods. Similarly, it has nothing to do with information hiding, although those are two interesting by-products of properties. Rather, the importance of properties is that properties support one aspect of the reflection process. The reflection process makes it possible for one object to discover and manipulate the properties, events, methods, constructors, fields, etc., belonging to another unknown object, at runtime, with no prior knowledge of the class from which the other object was instantiated. This, in turn, facilitates the development of very sophisticated software that makes heavy use of information about objects gained at runtime. A comparable Java program Now I'm going to show you a Java program that accomplishes exactly the same thing as the C# program discussed above. As with the C# program, the Java program illustrates properties from three significantly different viewpoints:
Also, as was the case with the C# program, the first two viewpoints were covered in Part 1 of this two-part lesson. The third viewpoint is the primary topic of this part of the lesson. While you might find it somewhat complex, I hope that you will stick with it until you understand the concepts involved. The most significant aspect of the third viewpoint will be the remarkable similarity between the C# code and the Java code, even at this complex level. Explain in fragments The complete Java program is shown in Listing J9 near the end of the lesson. As usual, in order to help you to focus on important sections of code, I will explain the behavior of this program in fragments. A target class As was the case with the C# program, the Java program consists of two classes. The first class, which was explained in detail in Part 1, is named TargetClass. This Java class mimics the behavior of the C# class shown in Listing C1. This class defines some properties, which are accessed by code in the
main
method of the other class named Props01. Listing J1 shows
the definition of the class named TargetClass in its entirety.
The boldface code in Listing J1 shows the definition of three properties
named color, height, and width.
An object of type TargetClass A Java object instantiated from the class named TargetClass contains:
The main method Listing J2 shows the beginning of the class named Props01 and
the beginning of the main method for that class. Except for
the difference in the signature of the main method, (which I
explained in an earlier lesson), the Java code in Listing J2 is identical
to the C# code in Listing C2.
The code in Listing J2 begins by instantiating and saving a reference to a new object of the class named TargetClass discussed above. The reference is saved in the reference variable named obj. The reference was used to access the public instance variable and the properties of this object in Part 1. In this part, the reference will be used in the introspection process to discover the properties belonging to the object at runtime. The user viewpoint As was the case with the C# program, we're getting ready to park the family station wagon and take a ride in a sports car. We will examine Java properties from the viewpoint of the sophisticated user of the class who needs to first discover and then use properties at runtime. The bottom line at the beginning I'm going to give you the bottom line up front. Our objective is to compare the process of discovering and manipulating properties in Java with the process of discovering and manipulating properties in C#. We will see that even though the names of the classes and methods that we will use to accomplish this purpose are different, the concepts and mechanisms involved are remarkably similar. Once you understand how to do this in one language, you should understand how to do it in both languages. Four steps This process will consist of four steps. (Recall that only three steps were required in C#. An extra step is required in Java.) If you compare the description of these Java steps with the descriptions of the steps required to accomplish the same thing in C#, you will find them to be almost identical. A Class object First I will get a reference to an object of the type Class, which represents the type of an object instantiated from the class named TargetClass.
A BeanInfo object Next I will use the Class object to get a reference to an object of type BeanInfo, which represents the class named TargetClass at a much deeper level than the object of the class named Class (this is the extra step that is required in Java). The object of type BeanInfo provides considerably more information about TargetClass than does the object of type Class.
An array of PropertyDescriptor objects Then I will use the BeanInfo object to get an array of objects of type PropertyDescriptor. (This corresponds to the second step in C#, which produces an array of objects of type PropertyInfo) This array will contain one object for each property belonging to the target object of type TargetClass. (From the previous discussion, you already know that the target object contains three properties, named color, height, and width. Therefore, the array will have three elements.) Iterate on the array Finally, I will iterate on the array object, using each object in the array to determine the name, type, and current value of the corresponding property belonging to the TargetClass object. Java and the Object class Listing J3 shows the first step in this process. (This Java
listing corresponds to the C# listing in Listing C3. Note that I
skipped the code in the main method that was covered in Part 1.)
Object defines eleven methods All classes in Java (and C# as well), derive either directly or indirectly from the class named Object. The class named Object defines eleven methods that are inherited into all other classes. Some methods may be overridden Some of those methods, (such as equals and toString), are intended to be overridden in new classes. In Java, they are virtual by default, so they may be freely overridden. Some methods are final Some of the methods, (such as getClass), are intended to be used as is, without overriding them. Those methods are declared final so that they cannot be overridden. Invoking the getClass method When the getClass method is invoked on an existing object, it returns a reference to an object of the type Class. According to Sun,
In Java jargon, it would be said that the Class object exposes the runtime type information (RTTI) of the object on which the method is invoked. Alternate ways to get a Class object I know of three ways to get a Class object in Java. One way is to invoke the getClass method on an object, as illustrated in Listing J3. (This is similar to invoking the GetType instance method in C#.) The second way is to invoke the static forName method of the Class class, passing the name of the target class as a String parameter. (This is similar to invoking the static GetType method of the Type class in C#.) The third way involves Class objects that represent primitive types. I will defer an explanation of that process until a future lesson. Step 1: Getting the Class object The code in Listing J3 invokes the GetClass method on the object instantiated earlier from the class named TargetClass. The GetClass method returns a reference to an object of the type Class. This object represents the class from which the object was instantiated; TargetClass in this case. The reference to the Class object is saved in the reference variable named theType. The Introspector class The discovery process in Java is described as introspection using low-level reflection. The class named Introspector plays an important role in this process. Here is what Sun has to say about the Introspector class:
Note that a Java Bean is a standard software component used in the Java version of software component programming. Step 2: Getting the BeanInfo object The Introspector class provides several static methods, including three overloaded versions of a method named getBeanInfo. The code in Listing J4 uses one of the overloaded versions of the getBeanInfo
method to get a BeanInfo object capable of providing information
about the target object earlier instantiated from the class named TargetClass.
(Since
there is no requirement for this step in C#, there is n C# code listing
corresponding to Listing J4.)
Two parameters required This version of the getBeanInfo method requires two parameters. The first parameter is a Class object representing the class from which the target object was instantiated; TargetClass in this case. The second parameter is also a Class object. This object represents a superclass of the target object. The resulting BeanInfo object will contain information about the target class and all of its superclasses up to, but not including the class represented by the second parameter. Use the direct superclass In this case, the second parameter was the direct superclass of the target class. Therefore, the resulting BeanInfo object contains information about the target class only (information about superclasses was precluded for simplicity). Step 3: Getting property information This step corresponds to the second step in the C# reflection process. We will get information about the properties defined in the class named TargetClass, which is now represented by the object of type BeanInfo. Several methods available The BeanInfo object provides several methods that can be invoked to get information about the type represented by the BeanInfo object. A few of those methods are shown in the following list to illustrate some of the information that is available. (In general, the names of the methods indicate the type of information they are designed to provide.)
Invoking the getPropertyDescriptors method The code in Listing J5 invokes the getPropertyDescriptors method
on the
BeanInfo object. (This is similar to invoking the
GetProperties
method on the
Type object in the C# program shown in Listing C4.)
PropertyDescriptor objects According to Sun, the getPropertyDescriptors method returns "An array of PropertyDescriptors describing the editable properties supported by this bean." An array of PropertyDescriptor objects The information is returned as an array of objects where each object in the array is of type PropertyDescriptor. Each object of type PropertyDescriptor represents one of the properties belonging to the target class under investigation. The number of properties In this case, the target class is the class named TargetClass. The number of elements in the array indicates the number of properties belonging to objects of the target class. Using the length property of the array As in C#, every array object in Java has a final public member variable (constant) named length, whose value is the number of elements in the array. In this case, the value of length
is the same as the number of properties belonging to the target class.
The code in Listing J6 gets and displays the value of length. (This
code corresponds to the code in the C# program shown in Listing C5.)
The number of properties The code in Listing J6 produces the following output on the screen, which matches what we already know about the number of properties defined in the Java class named TargetClass. (Recall that the Java class had three properties whereas the corresponding C# class had only two properties.) Number of Public Properties: 3 Getting information about each property Each of the PropertyDescriptor objects contained in the array
can be queried to obtain information about the specific property that it
represents. The code in Listing J7 displays some explanatory text
on the screen and then calls the method named DisplayPropertyInfo,
passing a reference to the array of PropertyDescriptor objects to
the method. (The Java code in Listing J7 corresponds to the C#
code in Listing C6.)
The DisplayPropertyInfo method As was the case with the C# program, the method named DisplayPropertyInfo is designed to get and display information from each element in the array. As a result, this method gets and displays information about each property in the class named TargetClass. The PropertyDescriptor objects Each object of the PropertyDescriptor type contains several methods that can be invoked to obtain information about the property that the object represents. For example, the name and the type of the property represented by the object can be obtained by invoking the methods named getName and getPropertyType on the PropertyDescriptor object.
Step 4: Iterate on the array of PropertyDescriptor objects The method named DisplayPropertyInfo receives a reference to the array of PropertyDescriptor objects as an incoming parameter. The entire method, consisting of a single for loop, is shown in Listing J8.
This method uses a for loop to iterate on the array, extracting name, type, and value information using each object stored in the array. Getting the name and type information is straightforward. As is the case in C#, getting the value information is a little more complicated.
Different issues As is the case in C#, there is a significant difference between name and type on one hand, and value on the other. The name and type of a property is the same for every object instantiated from a given class. However, the current value of the property will vary among different objects instantiated from the same class. Therefore, value is specific to each object instantiated from the class, while name and type are the same for all objects instantiated from the class. Getting the name and type The code to get and display the name and the type of the property represented by the PropertyDescriptor object is shown above the visual separator in Listing J8. As mentioned earlier, this code is straightforward. All that is required is to invoke the methods named getName and getPropertyType belonging to the PropertyDescriptor object. The values returned by these methods are the name and the type of the property represented by the PropertyDescriptor object. Getting the property value for a specific object The code required to get and display the value of a particular property for a specific object is shown below the visual separator in Listing J8. This code consists of the following steps (note that this is essentially the same process used to accomplish the same task in C#, as shown in Listing C7):
The Method class An object of the Method class provides information about, and access to, a single method on a class or interface. The reflected method may be a class method or an instance method (including an abstract method).
Numerous methods The Method object contains numerous methods that allow you to manipulate the method that it represents. For example, there is a method named getParameterTypes that you can use to get a list that identifies the number and types of parameters required by the method.
The invoke method of the Method class In this case, we are interested in the invoke method of the Method class. This method makes it possible to execute the get method represented by the Method object on a specific object of the TargetClass class. Two parameters required As was the case in C#, the Java invoke method requires two parameters. The first parameter is a reference to the object on which we want the get method to be invoked. In this case, this is the object of the class TargetClass, which has been the target of the investigation from the beginning. The second parameter is a reference to an array object, where each element in the array contains a reference to an object that is to be passed as a parameter to the method being invoked. In this case, the get method requires no parameters, so the code in Listing J8 passes null as the second parameter to the invoke method.
Invoking the get method on the target object The result of invoking the invoke method on the reference to the object of type Method, while passing the target object as a parameter, is to cause the get method to be invoked on the target object. The int value returned by the get method is picked up and returned by the invoke method. This value is passed to the println method in Listing J8, which causes it to be displayed on the computer screen. The screen output The screen output for the first iteration of the for loop in Listing J8 is shown below: Name: color
This output indicates that the name of the first property found by the introspection process was color. The property was of type int, and the current value was 15. We know from our prior knowledge of the behavior of the program that this is a correct report. The properties named height and width The screen output for the remaining two iterations of the for loop in Listing J8 is shown below: Name: height
Because we defined the TargetClass, and wrote the program that set the values of the three properties, we know these to be the correct name, type, and current value. However, prior knowledge of the answers is not a prerequisite for the correct operation of this introspection process. As in C#, the introspection process would work correctly if someone else had written the class named TargetClass and had provided us with only the compiled version of the class. Bound and constrained properties Properties in Java have an extra capability that apparently doesn't exist for properties in C#.
In Java, a bound property has the ability to register interested observer objects and to notify those observer objects each time the property value changes. A constrained property has the ability to do the same thing with the added stipulation that any observer of a constrained property has the right to veto the change. Toolbar buttons and menus A good example of the use of bound properties involves the construction of toolbar buttons that correspond to items on a menu. The toolbar button and the corresponding menu item should track one another in terms of being enabled and disabled. A toolbar button can register itself as an observer on the enabled property of a menu item. Each time the value of the enabled property of the menu item changes, the toolbar button will be automatically notified, and can change its own enabled property accordingly. See Understanding Action Objects in Java for a further discussion of this capability. SummaryConcentrate on properties This two-part lesson has concentrated on properties in C# and a comparison of C# properties with Java properties. A sample C# program was provided to illustrate C# properties. A sample Java program was also provided to illustrate the similarity of properties in C# and Java. Methods and fields C# properties act like methods to the creator of the class but look like public fields to clients of the class. As a result, public fields and properties are indistinguishable to readers of the code who don't have ready access to documentation on the class. Java properties look like methods to clients of the class. As a result, it is impossible to confuse properties with public fields in Java. In my opinion, Java properties are more self-documenting than C# properties. Beyond that, however, properties are used for essentially the same purpose in both languages. Properties support data hiding Both C# properties and Java properties provide the data hiding generally required by good object-oriented design. However, properties are not a prerequisite for data hiding. Data hiding can be easily accomplished in C#, Java, or C++ in the total absence of properties. Reflection and introspection The most important aspect of properties has to do with reflection and introspection. This is a process whereby one object can discover and manipulate the properties belonging to another unknown object even though the author of the executing program had no knowledge of the unknown object's class when the executing program was originally written. Bound properties and constrained properties Another important characteristic of properties has to do with bound properties and constrained properties. This is a process by which an object can be registered to be automatically notified when the value of a bound or constrained property changes. C# and Java properties are very similar Properties are so similar in C# and Java that if you understand properties in either language, you should have no difficulty understanding properties in both languages. What's Next?In the next lesson, I will teach you about indexed properties. These are properties containing multiple values, with each value being accessible through a numeric index. Complete Program ListingsA complete listing of the C# program discussed in this lesson is shown
in Listing C9.
A complete listing of the Java program discussed in this lesson is shown
in Listing J9.
Review QuestionsThese review questions apply to both parts of this two-part lesson. 1. True or false? C# properties look like methods to clients of the class while Java properties look like public fields to clients of the class. 2. True or false? C# properties provide the data hiding generally required by good object-oriented design, while Java properties do not provide such data hiding. 3. True or false? Properties are a prerequisite for the implementation of data hiding. 4. Which of the attributes in the following list are necessary for a property?
5. True or false? The value of a property must be stored in an instance variable of the object to which the property belongs. 6. What is the minimum number of matching pairs of curly braces { } required to define a property in C#? 7. What is the minimum number of matching pairs of parentheses () required to define a property in C#? 8. How are the name and type of a property established in C#? 9. What is the name of the standard C# class in which the non-static GetType method is defined? Is GetType a virtual method? 10. What is the return type of the GetType method in C#? 11. The Object class in Java defines a method with a similar purpose to the GetType method in C#. What is the name of the Java method? 12. What is the return type of the C# method named GetProperties, which is defined in the Type class? 13. What is indicated by the value of the Length property of the array object returned by the GetProperties method? 14. What is indicated by the values of the properties named Name and PropertyType belonging to an object of the type PropertyInfo? 15. What is the name of the method belonging to an object of the MethodInfo class that can be used to invoke the method represented by an object of the MethodInfo class? How many parameters does this method take, and what is the purpose of those parameters?
Richard has participated in numerous consulting projects and he frequently provides onsite training at the high-tech companies located in and around Austin, Texas. He is the author of Baldwin's Programming Tutorials, which has gained a worldwide following among experienced and aspiring programmers. He has also published articles in JavaPro magazine. Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.
AnswersAnswer 15The name of the method belonging to an object of the MethodInfo class that can be used to invoke the method represented by an object of the MethodInfo class is Invoke. The Invoke method requires two parameters. The first is a reference to the object on which the method is to be invoked. The second is an array containing the parameters that are to be passed to the method when it is invoked. Answer 14The values of the properties named Name and PropertyType belonging to an object of the type PropertyInfo indicate the name and the type of the property represented by the object of type PropertyInfo. Answer 13The value of the Length property of the array object returned by the GetProperties method is equal to the number of properties belonging to the object being investigated. Explanation 13The array object contains one object of type PropertyInfo for each property belonging to the object being investigated. Answer 12The return type is PropertyInfo[] Explanation 12The GetProperties method returns a reference to an array of PropertyInfo objects. Therefore, the return type is PropertyInfo[]. Answer 11The name of the Java method is getClass. Answer 10The return type for the GetType method is Type. Explanation 10The GetType method returns a reference to an object of the type Type. Therefore, the return type for the method is Type. Answer 9The non-static GetType method is defined in the Object class in C#. It is not a virtual method, because it is not intended to be overridden. (Note that a static version of the GetType method is defined in the Type class.) Answer 8The name and type of the property are established by the line that reads as follows in the definition of the property shown below: public int height{ Explanation 8
Here is the minimum syntax for the definition of
a property in C#. The first line is similar to a variable declaration
with the type of the property being established by the type in the declaration
and the name of the property being established by the name in the declaration.
Answer 7There are no parentheses required to define a property in C#. Explanation 7
Here is the minimum syntax for the definition of
a property in C#. Although get and set act like methods,
they do not have a formal argument list enclosed in parentheses.
Answer 6Three sets of matching curly braces are required to define a property in C#. Explanation 6
Here is the minimum syntax for the definition of
a property in C#.
Answer 5False Explanation 5The value of a property is probably most commonly stored in an instance variable belonging to the object, but that is not a requirement. The value could be stored in a database, or a disk file, or could be computed on-the-fly when requested. Answer 4
Answer 3False Explanation 3Properties are not a prerequisite for data hiding. Data hiding can easily be implemented in C#, Java, and C++ in the total absence of properties. Answer 2False Explanation 2Both C# properties and Java properties provide the data hiding generally required by good object-oriented design. Answer 1False Explanation 1The statement is backwards. A correct statement is, Java properties look like methods to clients of the class while C# properties look like public fields to clients of the class.
-end- |
© 1996, 1997, 1998, 1999, 2000, 2001, 2002 Richard G. Baldwin |