Thursday, January 17, 2008

Object Oriented Programming

OOP’s

We can say OOP’s is a nature of any languages, we can define a language Object Oriented,

If it has following features:

Part I: Using Objects

Intro to Objects and OOP

· Building a Class

· Instantiating Objects & the New statement.

· Constructors, Fields, Methods, Properties

· Accessibility: Public, Protected, Private, Internal, Virtual

Part II: Advanced Architecture

Implementation Inheritance

· Overriding Methods/Polymorphism

· Abstract Classes

· Aggregation/Composition

· Interfaces

Some of the Grander OOP Features

· Encapsulation – Objects are by nature, encapsulated. That is, only certain portions of their fields and methods are publicly accessible from other classes and one doesn’t really need to know the inner workings of an object in order to use it. Encapsulation has certain benefits. By hiding the inner workings of a class, it makes that class simpler to use because the developer only sees and has access to what is necessary to use the class. Furthermore, the developer cannot accidentally override the data inside that class.

· Inheritance – Often considered the "Holy Grail" of programming inheritance is just as often misused or misunderstood. Inheritance defines a particular ability of classes to inherit the data members and functionality from other more generalized classes. The new or "child" class can than add more specific functionality that is parent does not possess.

· Polymorphism – Polymorphism is even more difficult to understand and explain. Literally meaning "many forms" polymorphism is the ability for related classes to have the methods or functions with the same name and syntax but different implementations.

· Aggregation/Composition – Although these two terms are often used interchangeably, aggregation is more generalized term referring to groups of objects being used to make up another object, much the way a car is made of various parts. Composition is a much more specific form of aggregation where one the pieces can only belong to one whole and outside of that whole, they no longer exist. Usually though, you’ll hear people refer to composition in the more general sense that aggregation defines.

· Interfaces – Perhaps one of the most mysterious features of OOP languages, interfaces have very specific purposes, especially in component development. Classes that inherit interfaces are required to have certain methods, fields and/or properties defined and implemented. This allows related classes to have a consistent manner of using them. For example, all the .NET collection classes inherit from the IEnumerator interface, forcing them to have the methods MoveNext(), Reset() and Current property.

Creating Classes

To use these features, you are going to have to think and code in terms of classes. Where both VB 6 and C++ allow you to write as OOP or non-OOP as you desire, .NET is designed to more consistently encourage (or force) you to write your applications as groups of classes. To declare a class in VB.NET, most of the time you would use the following:

Public Class ClassName

...

End Class

This creates a public class, i.e., a class that can be used by any application not just the one it was written for. Most classes are declared as public. We’ll discuss what this means shortly. Also, it is important to note that you can declare multiple classes within the same file, but most of the time, it is a better practice to limit one class per file. I also usually make the filename the same as the class name. So if I named my file books, the class it contains should be Books.vb (or Books.cs if you are using C#.)

To use a class in VB.NET, you instantiate it. This initializes the class and creates an object based upon it. You can give each object any name and create multiple instances of the same or different classes in your code. Instantiating a class is done using the New statement:

Dim ObjectName as ClassName

ObjectName = new ClassName(Optional Parameters)

However, it is important to note that even simple values such as String’s and Integers are classes as can be seen through the following code snippet:

Dim email As String

email = "buygreatbooksatwrox.com"

If email.IndexOf("@") <>

Response.Write(email + " is a bad email address.")

End If

In the code above, I declare the variable email as a string and give it a default value of "buygreatbooksatwrox.com". The syntax isn’t much different than how I would declare a string in a procedural language. Yet, email is itself an object of the string class, even though we haven’t defined it as such. I can use the built-in IndexOf method on it to look for an "@" symbol and determine if this is a valid email address (in a sloppy fashion, I admit).

Finally, you should be aware that every class you create automatically inherits from at least one class in the .NET framework: the Object class. Remember that I mentioned earlier that inheritance means that one class inherits members (fields, methods and properties) from another.

Class Members

To get more granular, classes themselves are made up of members. Members generally consist of the class’ data (or fields) and its functionality (or methods). Both C# and VB (and presumably nearly all .NET languages) build classes using constructs below.

· Constructors – Constructors are procedures that run when a class is instantiated as an object using the new statement mentioned above. They are useful for initializing values in fields or properties (see below) or running any other code that needs to run when an object is instantiated. A constructor is defined as follows:

Public Sub New()

... 'Code to make the Constructor do something

End Sub

Since constructors cannot return values, the VB.NET compiler will return an error if you try to define a Constructor as a Function rather than a Sub.

· Fields – While variables can be declared anywhere, fields are variables declared at the beginning of the class definition. A variable declared as a field is accessible from anywhere in that class. Variables declared within a function or procedure, are only accessible within that function or procedure. Furthermore a variable can be a simple value such as a character or integer, or a more complex value such as another object. To define a public field in VB.NET you would use the following:

Public FieldName as ValueType

...

End Sub

Fields are accessed from outside of your class using the following syntax:

Value = ObjectName.Fieldname

ObjectName.Fieldname = NewValue

· Methods – Functions and Procedures in VB are methods. They are defined within a class and therefore a member of that class.

Public Sub MethodName()

...

End Sub

or to write a function that will return a value:

Public Function MethodName() As ValueType

...

return newvalue

End Function

· Properties – A good analogy for Properties might be to consider them a "hybrid": a cross between a field and a method. If you have used properties in VB 6, they haven’t changed that much. When defined within your code, properties can perform any code that a method can and usually (although not necessarily) encapsulate a matching field within the class. However, when used from another class, properties are accessed as if they are standard fields. This enables the developer writing the properties to ensure that the fields they manipulate never get set to values that would cause errors or data loss within your software. A "Get" block in the property definition is created with code that executes when the property is read. Then a "Set" block is created to define what values in the class change when the property is written to. In their simplest form, properties are defined in the manner below. But it is important to note that within the Get and Set blocks, and code can be written to make the properties do something.

Public Property PropertyName() As ValueType

Get

Return Value

End Get

Set(ByVal Value As ValueType)

FieldName = Value

End Set

End Property

When the properties are read from, they are accessed as if you are reading a field from an object:

SomeValue = MyObject.Property

Similarly, when written to, the property is accessed like so:

MyObject.Property = NewValue

Be aware that in VB.NET, unlike VBScript and VB6, there are not default properties. If you refer to an object in your code, there is no default property that will return a value – you’ll be changing or reading the reference to that object.

Member Accessibility

· Public – At this level of access, the data member can be accessed from outside the class by any other class.

· Protected – A protected member can only be accessed by members within the same class, or by a derivative of that class using Inheritance. We’ll get to inheritance and protected methods later on.

· Friend – A member declared as Friend can be accessed by any other class in the same project.

· Protected Friend – the best of the previous two access levels, protected friend means the member can be accessed by the same class, a derivative class or any classes in the same project.

· Private – This is the most restrictive access you can define within a class. A member defined as Private can only be accessed within that class. If you define a member using only the Dim statement, the member is considered Private. However, it is a better practice to use Private instead of Dim to declare these types of members and it is easier to read and understand.

Using Objects in ASP.NET

In order to start small, we’ll write three simple files. you can start a new project called ASPObjectsVB. We’ll create our first class, Appliance.vb. We’ll also create our web page, DisplayPage.aspx and it’s code-behind file DisplayPage.aspx.vb.

Appliance.vb

Public Class Appliance

'_power is used internally as a true/false switch for

'whether the appliance is on.

Protected _power As Boolean

'The CurrentPower property gives us a more natural way

'of saying whether the power is on than the "_power" boolean

'field above

Public Property CurrentPower() As String

Get

If _power = True Then

Return "On"

Else

Return "Off"

End If

End Get

Set(ByVal Value As String)

If Value = "On" Then

_power = True

Else

_power = False

End If

End Set

End Property

'When the appliance is first created, the power is off.

Public Sub New()

TurnOff()

End Sub

'While the CurrentPower property does almost the same thing

'As these two functions/methods, they demonstrate the use

'of methods now and help us demonstrate inheritance and polymorphism

'later.

Public Overridable Function TurnOn() As String

Me.CurrentPower = "On"

Return GetStatus()

End Function

Public Overridable Function TurnOff() As String

Me.CurrentPower = "Off"

Return GetStatus()

End Function

'Since all classes inherit from the Object class, I can use the

'GetType() method in this helper function to figure out what class

'this object is, programmtically. This is useful when using inheritance,

'especially during development and debugging.

Private Function GetStatus() As String

Return "The " & Me.GetType().ToString() & "'s Power is " & Me.CurrentPower

End Function

End Class

The first line of code creates our class Appliance. Next we define a field called _power. Remember fields are variables that are declared right after the class definition (as opposed to being declared inside a function or procedure) and can be accessed by any methods (procedures or functions) inside that class. I declared this as protected so that it is not publicly accessible outside this class but can still be inherited by other classes. The _power field is a Boolean variable, because it will represent whether the power is on or off. Boolean is the closest data type for this type of value as it also can only be in one of two states: true or false.

About Properties

The next member to be defined is the CurrentPower property. While it might be handy to emulate "Power" as a Boolean value (true / false) from inside our class, at other times it is more humanly readable to refer to the power as "On" or "Off". For this, we’ve constructed a public property called CurrentPower. CurrentPower acts as wrapper for the protected _powe r field. From outside the class, we can set the _power field to True by passing the CurrentPower property a string value called On. This is written in the Set block. Similarly, when we read the CurrentPower field, it will check the _power field and if it is true, it will return the string Off. This is defined in the Get block of code and uses the Return statement to send back the On or Off string. The CurrentPower property keeps our Appliance object in a consistent state, so that if the user of the class puts in something strange instead of On or Off the property will set our _power field to false by default.

This is a good practice and partially what properties are designed for. Most developers do not make their fields public as it makes the class easy to break easily and violates encapsulation. Instead, they use properties or methods to manipulate private or protected fields and ensure that the fields never have an illegal value.

In Java, there are no properties in the sense that Microsoft has provided us with VB and C#. Instead, the developer must make something called "Get" or "Set" methods that modify the internal fields. For example to Set a property in Java, you would actually be making a call to a method similar to the following:

ObjUser.SetName(username);

Compare this to VB.NET:

ObjUser.Name = username

Me

In appliance.vb, I am using the prefix Me for many of my variables. In C#, Jscript, Java and C++ this prefix is called this but essentially means the same thing. While it’s not always necessary, it’s often useful for documentation purposes to prefix your class fields so you know they are fields and not just a variable local to a method. If you declare a variable inside a method with the same name as one of your fields, than you MUST use the Me to scope your variable when you want to reference the field. Otherwise, the compiler believes you are referencing the variable local to that function or procedure.

The Constructor

Next, we define our constructor with the following code:

Public Sub New()

TurnOff()

End Sub

Remember that the constructor will run when we first initialize our class or use it in another program. We’ll do this shortly. Our constructor here simply calls the TurnOff() function. This makes sense, as most appliances are not automatically running as soon as you buy them.

The TurnOn() and TurnOff() methods are pretty simple and admittedly, exist in our code more for educational purposes. We already have the CurrentPower property to programmatically set the power on or off. However, these two methods are handy as a quick way to do the same thing. They also return a string value by calling our GetStatus() method which is useful for display purposes. After the methods turn the power on or off using the CurrentPower property, they call the get status to return a string. Let’s look at the GetStatus() method:

Private Function GetStatus() As String

Return "The " & Me.GetType().ToString() & "'s Power is " & Me.CurrentPower

End Function

The function is returning a string that starts with the Return statement. This means that the string that we build is going to immediately return to the code that executed the GetStatus() method. We then append Me.GetType().ToString(). This looks complicated but is actually pretty simple. Remember that all our classes inherit from the .NET base class Object. We use Me.GetType() which returns the Type of class we’re using. Type, by the way, is a generic reference in .NET to data types such as integers, strings, arrays and objects. You can use the GetType() method on any object to ask it what class it belongs to. In this case, it is the Appliance class. We then use the ToString() method on that type which returns the name of the class as a string. Again, ToString() is another method built into .NET. You’ll see this later. Finally we append more text to the string to display whether the power is on or off.

DisplayPage.aspx.vb

Imports System.Threading

Public Class DisplayPage

Inherits System.Web.UI.Page

Protected WithEvents lblDisplay As System.Web.UI.WebControls.Label

#Region " Web Form Designer Generated Code "

'This call is required by the Web Form Designer.

Private Sub InitializeComponent()

End Sub

Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init

'CODEGEN: This method call is required by the Web Form Designer

'Do not modify it using the code editor.

InitializeComponent()

End Sub

#End Region

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)

Handles MyBase.Load

'Put user code to initialize the page here

Dim appl As New Appliance()

Me.lblDisplay.Text = appl.TurnOn()

Me.lblDisplay.Text &= "
" & appl.TurnOff()

'We can just use the TurnOn() function without doing anything

'with the string it returns. It will still turn the apppliance 'on.

appl.TurnOn()

Me.lblDisplay.Text &= "
Our Appliance's CurrentPower property is " & appl.

CurrentPower()

'We can write to the CurrentPower property if we wish:

appl.CurrentPower = "Off"

Me.lblDisplay.Text &= "
Using the property, we turned it back off."

Me.lblDisplay.Text &= "
The appliance is " & appl.CurrentPower

End Sub

End Class

Part 2

Part II: Advanced Architecture

· Implementation Inheritance

· Overriding Methods/Polymorphism

· Abstract Classes

· Aggregation/Composition

· Interfaces

Using Implementation Inheritance

With inheritance we are attempting to develop a relationship between a generalized class and more specialized child classes. Inheritance also encourages a lot of code reuse. If you find yourself making several classes that have very similar functionality, and conceptually are in a similar category of objects, it might make sense to create an inheritance structure. The parent of this structure is known as the base class or super class. We can write the common or generalized functionality here. The child or sub-classes then inherit from the base class. These sub-classes then can have functionality found neither in the base class nor in the other child classes. This is known as extending a class. If you want to add new functionality to all the child classes, you need only modify the base class.

Inheritance is used frequently in the .NET base classes. In ASP.NET, examples of inheritance abound. An .aspx page is actually just a class that inherits from its .aspx.cs code-behind class. The code-behind, in turn must inherit from the System.Web.UI.Page class, or inherit from another class that does so. This enables you to put logic into the code-behind separated from the display and HTML code in the .aspx page. All web forms, whether an .aspx page or its code-behind file in turn inherit from System.Web.UI.Page. This in turn inherits from a whole chain of other .NET classes. In fact, much of the .NET framework is structured in an inheritance hierarchy. However, the real value of inheritance is making your own hierarchies that accurately model real world entities and solve real world problems. Thus, it is necessary to learn to use inheritance in your own code.

The relationship between parent classes and their child or sub classes is often referred to as an "is a" relationship. A good example of inheritance is in the realm of electronic appliances. A TV is an appliance. A stereo system is an appliance. A computer also is an appliance. All of these objects: stereos, computers, TV’s etc. have an "is a" relationship with "appliance" i.e. each of them "is an" appliance. As such, they will all share certain characteristics such as electrical circuits, a power cord, an on/off switch, etc.


You could create a special kind of diagram to model these items as classes. This is known as a class diagram:

Figure 1: The Clock and Stereo classes inherit from the Appliance class. The arrows represent a relationship known as a "Generalization" in UML. Appliance is a more generalized object than Clock or Stereo.

This simple class diagram shows the inheritance relationship between classes Appliance, Stereo and Clock. The up arrows represents a "Generalization" that is, Clock and Stereo are classes that come from the more generalized device, Appliance. You might have seen this type of diagram in a school, training class or elsewhere on the web. But how does this translate to code?

In ASP 3, you could make classes by writing COM objects in Visual Basic 6 or VBScript. However, any methods or fields in Appliance would then have to be copied and pasted to Clock and Stereo. Implementation inheritance was not supported, so functionality and changes to code in the Appliance class would not "trickle down" to Stereo or Clock. Now, VB6 did have something called interface inheritance, which is still supported in .NET, but as we’ll see later this "interface inheritance" does not allow changes to trickle down in the same manner or enable the developer to reuse code. These changes would instead have to be manually altered in the other sub-classes, or some other method of code reuse that is perhaps not as natural as inheritance would have to be used instead. Furthermore, while writing COM objects in Visual Basic 6 was fairly simple it was still a bit different than writing VBScript. It also meant switching to a different IDE and compiling and registering an ActiveX DLL on the server. This added another level of complexity to developing object-oriented web applications.

Based upon our model of Appliance, Clock and Stereo, we’ll make an inheritance hierarchy that matches the diagram above. We’ll create a base class, Appliance and give it some very simple functionality. Then we’ll make 2 classes to inherit from it, one called Clock and one called Stereo.

In Part I, we created the Appliance class. In case you missed it, or to refresh your memory, Appliance.vb looked like this:

Stereo.vb

Public Class Stereo

Inherits Appliance

Protected _volume As Integer

Public ReadOnly Property CurrentVolume() As Integer

Get

Return _volume

End Get

End Property

Public Overrides Function TurnOff() As String

Me._volume = 0

Return MyBase.TurnOff()

End Function

Public Sub TurnUpVolume()

If _volume < currentpower = "On">

_volume += 1

End If

End Sub

Public Sub TurnDownVolume()

If _volume > 0 And Me.CurrentPower = "On" Then

_volume -= 1

End If

End Sub

End Class

Stereo is also a very simple class. We use the Inherits statement to tell the VB.NET compiler that our child class Stereo will inherit all the functionality from our base class Appliance. To read the current volume of the Stereo, we have a ReadOnly Property called CurrentVolume(). Since we marked it as ReadOnly, there is only a Get block here. When we use this class, we will not be able to set the volume using the CurrentVolume() property. Instead we use the TurnUpVolume() and TurnDownVolume() methods for that. As you can see, these methods allow a maximum volume of 10 and a minimum volume of zero. However, there is a neat safety feature here. The volume can only be changed if the CurrentPower is "On". This ensures that when someone turns on the stereo, the volume cannot already be set to 10, giving the owner a heart attack the way so many teenaged sons have done using their father’s car stereos.

Some Polymorphism: Overriding Methods

Polymorphism, which means "many forms", refers to the ability for the same method to be implemented differently in different classes. The TurnOff() function is defined in this class even though it is already defined in our base class Appliance. This is called overriding a method (not to be confused with overloading a method, which we’ll also look at in just a moment). Using the Overrides keyword, we tell the compiler that we are going to define a new version of our TurnOff() method instead of using the one we inherited. In this case, all we are doing differently is ensuring that _volume is set to zero whenever the stereo is turned off. After all, it wouldn’t make much sense for there to be a volume of 5 if the stereo has no power. We also do something else a little different, but common in OOP architecture. We call the original TurnOff() method defined in our base class. Using the keyword MyBase, we refer back to the method defined in Appliance, our base class. So we haven’t lost any of the functionality in our base class by overriding this method. We can still call the original method using MyBase.TurnOff(). If you were to set a break point at this line of code, then step through the code using a debugger, you would actually see the execution jump from Stereo.vb to Appliance.vb after it executes this line of code. This technique of changing the definition of a method from one class to another is part of that concept of Polymorphism. The method TurnOff() literally does have "many forms".

So in essence we get "the best of both worlds". We can make a new TurnOn() method but always get access to the old TurnOn() method using the MyBase keyword. We have essentially said to the compiler: "We want to redefine the TurnOn() method for Stereo, so that it will set the volume to zero. Then it will do what any other Appliance would do: turn the power off".

If you’ve worked in Java, this would be all you would need to do. However, .NET is a little pickier about overriding a method in this fashion. It wants to make sure you really, really want to override a method defined in some parent class, or allow other developers to do the same. So in order to do this, our original Appliance.vb had to have each method set to Overrideable :

Refer Appliance.vb for overridable

More Polymorphism: Overloading Methods

The Clock class will be conceptually very similar to the Stereo class. We’ll inherit from Appliance as well as define some new fields, properties and methods.

Clock.vb

Public Class Clock

Inherits Appliance

Protected _time As DateTime

Protected CurrentFormat As TimeFormat

Public Enum TimeFormat

Standard = 0

Military = 1

End Enum

Public ReadOnly Property CurrentTime() As String

'I only want the user to be able to set the time,

'so this property is ReadOnly

Get

'We're using this "If" statement to emulate

'the clock being turned "off"

If Me.CurrentPower = "On" Then

_time = DateTime.Now

End If

If Me.CurrentFormat = TimeFormat.Military Then

Return _time.ToString("HH:mm:ss")

Else

Return _time.ToString("h:mm:ss tt")

End If

End Get

End Property

Public Sub New()

_time = DateTime.Now

SetMilitary()

End Sub

Public Sub New(ByVal startformat As TimeFormat)

_time = DateTime.Now

Me.CurrentFormat = startformat

End Sub

Public Sub SetMilitary()

Me.CurrentFormat = TimeFormat.Military

End Sub

Public Sub SetStandard()

Me.CurrentFormat = TimeFormat.Standard

End Sub

End Class

We’re introducing only a couple of simple, new concepts in this class. First, I create a special data type known as an Enumeration. I do this with the Enum statement. Enumerations are very useful things to have inside your VB and C# classes. They act kind of like user-friendly constants and each item in the enumeration acts an integer, float or other numeric value. As such, they are value types so when you assign an existing enumeration to a variable, you are copying that enumeration’s current value. I created an Enum called TimeFormat, in which I specify Military time or standard AM/PM style of formatting for our clock.

Enums act as kind of constant, where a series of variables represents some sort of numeric value. Instead of making our TimeFormat Enum, I could have just defined some plain old constants:

Public Const Standard = 0

Public Const Military = 1

However, creating enumerations groups related constants together. In our case we have TimeFormat.Military and TimeFormat.Standard. This makes it easier to read and write our code. We know that Military is a time format when reading our code. Also, when writing any code that calls a method, property or field that uses our enum, an IDE such as VS.NET will pop-up intellisense prompts for one of the two values in our Enum.

The other important concept in the Clock class is the definition of our constructor:

Public Sub New()

_time = DateTime.Now

SetMilitary()

End Sub

Public Sub New(ByVal startformat As TimeFormat)

Me.New()

Me.CurrentFormat = startformat

End Sub

As you can see, the New() sub-routine which is our constructor, is defined twice. In the first, it accepts no parameters, but in the second it accepts a parameter called startformat which uses our Enumeration as its data type. This is known as overloading a method. In our case, we are using something called constructor overloading. Recall that the constructor gets called only when the class is first created. However, it is possible to overload any method within your classes. Finally, on the second version of our constructor, we have the line that says: Me.New(). We are having our second (overloaded) constructor make a call to the first, parameterless, constructor. This is done on the first line of the second New() subroutine. Visual Basic will not allow you to put this call anywhere else in the subroutine.

It is easy to get overloading and overriding methods confused because of the similar names and the fact that both are related to Polymorphism. With overriding, we redefined a method in a child or sub class that had previously been defined in its base class. Overloading a method, on the other hand, isn’t related to inheritance or parent/child classes. Instead, overloading refers to the ability to define as many versions of the same method that we want. Each version must have the same name and return type (if any), but it also must have a different set of acceptable parameters.

We’ll modify that file’s code-behind class (DisplayPage.aspx.vb) in part 1, to see our Stereo and Clock classes in action.

I’ll change our DisplayPage code-behind to use the StringBuilder class to append text together for our lblDisplay that shows our classes being manipulated. It’s a good practice to get into, as the StringBuilder has better performance than simply adding strings together (see Wayne Plourde's article: Enhancing Performance Part 3).

DisplayPage.aspx.cs

Private Sub Page_Load(ByVal sender As System.Object,

ByVal e As System.EventArgs) Handles MyBase.Load

'In this version, we'll use a string builder to create our output.

'It's a good practice that improves performance.

displayText = New StringBuilder()

Dim appl As New Appliance()

Me.displayText.Append(appl.TurnOn())

Me.displayText.Append("
" & appl.TurnOff())

'We can just use the TurnOn() function without doing anything

'with the string it returns. It will still turn the apppliance

'on.

appl.TurnOn()

Me.displayText.Append("
Our Appliance's CurrentPower property is

" & appl.CurrentPower)

'We can write to the CurrentPower property if we wish:

appl.CurrentPower = "Off"

Me.displayText.Append("
Using the property, we turned it back off.")

Me.displayText.Append("
The appliance is " & appl.CurrentPower)

Dim stereo As New Stereo()

stereo.TurnUpVolume()

stereo.TurnUpVolume()

Me.displayText.Append("

The stereo is " + stereo.CurrentPower)

Me.displayText.Append("
The stereo's volume is " & stereo.CurrentVolume)

Me.displayText.Append("
" + stereo.TurnOn())

stereo.TurnUpVolume()

stereo.TurnUpVolume()

stereo.TurnUpVolume()

Me.displayText.Append("
The stereo's volume now is " & stereo.CurrentVolume)

Dim clock As New Clock(clock.TimeFormat.Standard)

clock.TurnOn()

Me.displayText.Append("
the clock's time is: " & clock.CurrentTime)

Thread.Sleep(2000)

Me.displayText.Append("
the clock's time is: " & clock.CurrentTime)

Me.lblDisplay.Text = Me.displayText.ToString()

End Sub

There are a few things of interest here. We instantiate our Stereo class and attempt to turn up the volume before we call its TurnOn() method. You’ll see in the screenshot below this doesn’t have any affect, the volume remains at zero. Next, after we turn the stereo on, you’ll notice we called the TurnUpVolume() three times to incrementally raise the volume of our Stereo class to 3. Thirdly, when we instantiated our Clock class using the New() keyword, we passed it one of the values in our TimeFormat Enumeration:

Dim clock As New Clock(clock.TimeFormat.Standard)

We instantiated the Clock class using the overloaded constructor that accepts the TimeFormat enumeration as a parameter instead of just specifying New Clock() which would have just defaulted to military time. As a result, the clock will display time in Standard AM/PM format.

The Clock class is just a wrapper for .NET’s native DateTime class, so we use the Thread.Sleep() method to allow some time to pass to see a difference from one call of our CurrentTime property to another. You may want to change this line to Thread.Sleep(0) from now on so you don’t have to wait the extra 2 seconds each time you view this page.

Aggregates and Composition

What’s the difference between aggregation and composition? Aggregation is a broader model in which a child object is embedded into one or more parent objects. For example, if you have two classes, each with a DataSet as one of their fields or properties, and the first class passes the DataSet to another class, this is an aggregation. However, our Label in our DisplayPage.aspx page is an example of composition. This is because the object lblDisplay is not used in any other class. Thus, it belongs only to one object at a time and falls under the category of Composition.

Using Classes with Web Forms

ClockRadio.vb

ClockRadio.vb

Public Class ClockRadio

Inherits Stereo

'This clock is "built-in" to our stereo. We are now using Composition.

Protected Friend StereosClock As Clock

Public Sub New()

MyBase.New()

'We have to instantiate our clock inside this stereo or

'it won't work. We also leave it turned on all the time.

StereosClock = New Clock()

Me.StereosClock.TurnOn()

Me.StereosClock.SetStandard()

End Sub

End Class

ClockRadioGUI.aspx

<%@ Page Language="vb" AutoEventWireup="false" Codebehind="ClockRadioGUI.aspx.vb" Inherits="ASPObjectsVB.ClockRadioGUI"%>

DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<HTML>

<HEAD>

<title>ClockRadioGUItitle>

HEAD>

<body ms_positioning="GridLayout">

<TABLE height="327" cellSpacing="0" cellPadding="0" width="105" border="0" ms_2d_layout="TRUE">

<TR vAlign="top">

<TD width="105" height="327">

<form id="Form1" method="post" runat="server">

<TABLE height="88" cellSpacing="0" cellPadding="0" width="315" border="0" ms_2d_layout="TRUE">

<TR vAlign="top">

<TD width="9" height="12">TD>

<TD width="1">TD>

<TD width="29">TD>

<TD width="6">TD>

<TD width="41">TD>

<TD width="52">TD>

<TD width="24">TD>

<TD width="153">TD>

TR>

<TR vAlign="top">

<TD colSpan="2" height="1">TD>

<TD rowSpan="2">

<asp:Button id="btnPower" runat="server" BackColor="Lime" Width="20px" Height="20px">asp:Button>TD>

<TD colSpan="5">TD>

TR>

<TR vAlign="top">

<TD colSpan="2" height="49">TD>

<TD colSpan="3">

<asp:LinkButton id="lbtnPower" runat="server">

POWERasp:LinkButton>TD>

<TD colSpan="2">

<asp:Label id="lblClock" runat="server" Height="33px" Width="175px" Font-Bold="True" Font-Size="Large">asp:Label>TD>

TR>

<TR vAlign="top">

<TD height="3">TD>

<TD colSpan="2" rowSpan="2">

<asp:Button id="btnVolUp" Text="+" Width="25px" Height="25px" Runat="server" Font-Bold="True">asp:Button>TD>

<TD rowSpan="2">TD>

<TD rowSpan="2">

<asp:Button ID="btnVolDown" Runat="server" Text="-" Width="25px" Height="25px" Font-Bold="True">asp:Button>TD>

<TD colSpan="3">TD>

TR>

<TR vAlign="top">

<TD height="23">TD>

<TD colSpan="2">

<asp:Label id="Label1" Runat="server">VOLUMEasp:Label>TD>

<TD>

<asp:Label ID="lblVolumeLevel" Runat="server" Font- Bold="True">asp:Label>TD>

TR>

TABLE>

form>

TD>

TR>

TABLE>

body>

HTML>

ClockRadioGUI.aspx.vb

Public Class ClockRadioGUI

Inherits System.Web.UI.Page

Protected WithEvents lblVolumeLevel As System.Web.UI.WebControls.Label

Protected WithEvents btnVolUp As System.Web.UI.WebControls.Button

Protected WithEvents btnVolDown As System.Web.UI.WebControls.Button

Protected WithEvents Label1 As System.Web.UI.WebControls.Label

Protected WithEvents btnPower As System.Web.UI.WebControls.Button

Protected WithEvents lbtnPower As System.Web.UI.WebControls.LinkButton

Protected WithEvents lblClock As System.Web.UI.WebControls.Label

Protected MyClockRadio As ClockRadio

#Region " Web Form Designer Generated Code "

'This call is required by the Web Form Designer.

Private Sub InitializeComponent()

End Sub

Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs)

Handles

MyBase.Init

'CODEGEN: This method call is required by the Web Form Designer

'Do not modify it using the code editor.

InitializeComponent()

End Sub

#End Region

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)

Handles

MyBase.Load

If Session("MyClockRadio") Is Nothing Then

MyClockRadio = New ClockRadio()

Session.Add("MyClockRadio", MyClockRadio)

Else

MyClockRadio = Session("MyClockRadio")

End If

End Sub

Private Overloads Sub OnPreRender(ByVal sender As System.Object, ByVal e As

System.EventArgs)

Handles MyBase.PreRender

If MyClockRadio.CurrentPower = "On" Then

Me.btnPower.BackColor = Color.Red

Else

Me.btnPower.BackColor = Color.Black

End If

Me.lblVolumeLevel.Text = MyClockRadio.CurrentVolume

Me.lblClock.Text = MyClockRadio.StereosClock.CurrentTime

End Sub

Private Sub btnPower_Click(ByVal sender As System.Object, ByVal e As

System.EventArgs) Handles

btnPower.Click, lbtnPower.Click

If Me.MyClockRadio.CurrentPower = "On" Then

MyClockRadio.TurnOff()

Else

MyClockRadio.TurnOn()

End If

End Sub

Private Sub btnVolUp_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)

Handles

btnVolUp.Click

MyClockRadio.TurnUpVolume()

End Sub

Private Sub btnVolDown_Click(ByVal sender As System.Object, ByVal e As

System.EventArgs) Handles

btnVolDown.Click

MyClockRadio.TurnDownVolume()

End Sub

End Class


0 Comments: