Properties versus Fields
When you set or read a property’s value, the corresponding Get or Set segment of the Property procedure is executed. The following statement invokes the Property Set segment of the EMail public property of the class:
cust.EMail = "[email protected]"
Obviously, every time you call one of the class’s properties, the corresponding public procedure in the class is invoked. The following statement invokes both the Set and Get property procedures of the Customer class’s Balance property:
cust.Balance = cust.Balance + 429.25
Trivial properties can also be implemented as public variables. These variables, which are called fields, behave like properties, but no code is executed when the application sets or reads their value. We often implement properties of the enumeration type as fields because they can be set only to valid values. If the Set method of a property doesn’t contain any validation code and simply assigns a new value to the local variable that represents the specific property, there’s no difference between the property and a field.
Shared versus Instance Members
To really understand classes and appreciate them, you must visualize the way classes combine code and data. Properties contain the data that live along with the code, which determines the object’s behavior its functionality. The functionality of the object is implemented as a number of methods and events. The properties, methods, and events constitute the class’s interface. Each instance of the class acts on its own data, and there’s no interference between two objects of the same type unless they contain shared properties. A shared property is common to all instances of the class. In other words, there’s no local variable for this property, and all instances of the class access the same variable. Shared properties are not common — after all, if many of the properties are common to all instances of the class, why create many objects? Shared methods, on the other hand, are quite common. The Math class is a typical example. To calculate the logarithm of a number, you call the Log method of the Math class:
You need not create an instance of the Math class before calling any of its methods (which are the common math functions). Actually, you can’t create a new instance of the Math class because the entire class is marked as shared.
Let’s say you’re building a class to represent customers, the Customer class. This class should expose properties that correspond to the columns of the Customers table in a database. Each instance of the Customer class stores information about a specific customer. In addition to the properties, the Customer class should expose a few methods to get data from the database and commit changes or new customers to the database. The GetCustomerByID method, for example, should accept the ID of a customer as an argument, retrieve the corresponding customer’s data from the database, and use them to populate the current instance’s properties. Here’s how you use this class in your code:
Code language: CSS (css)
Dim cust As New Customer cust.GetCustomerByID("ALFKI") Debug.WriteLine cust.CompanyName Debug.WriteLine cust.ContactName & " " & cust.ContactTitle
The GetCustomerByID method can retrieve the customer data from a local database, a remote web service, or even an XML file. The idea is that a single method call gets the data and uses it to populate the properties of the current instance of the class. This method is an instance method because it requires an instance of the class. It populates the properties of this instance, or object. You could have implemented the GetCustomerByID method as a shared method, but then the method should return an object of the Customer type. The shared method can’t populate any object’s properties, because it can’t be applied to an instance of the class. Here’s how you’d use the Customer class if the GetCustomerByID method were shared:
Code language: PHP (php)
Dim cust As New Customer cust = Customer.GetCustomerByID("ALFKI") Debug.WriteLine cust.CompanyName Debug.WriteLine cust.ContactName & " " & cust.ContactTitle
As you can see, we call the method of the Customer class, not the method of an object. You could also call the method with the following statement, but the code becomes obscure (at the very least, it’s not elegant):
cust = cust.GetCustomerByID("ALFKI")
The background compiler will detect that you’re attempting to access a shared method through an instance of the class and will generate the following warning. (The expression will be evaluated at runtime, in spite of the warning.)
Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated.
Because the class needs to know the database in which the data is stored, you can provide a Connection property that’s shared. Shared properties are usually set when the class is initialized, or from within a method that’s called before we attempt to access any other methods, or any of the class’s properties. All the methods in the class use the Connection property to connect to the database. There’s no reason to change the setting of this property in the course of an application, but if you change it, all subsequent operations should switch to the new database.
In summary, any class may expose a few shared properties, if all instances of the class should access the same property value. It may also expose a few shared methods, which can be called through the class name, if there’s no need to create an instance of the class in order to call a method. In extreme situations, you can create a shared class: All properties and methods of this class are shared by default.