Class Abstraction and Shadowing |
|
Fundamentals of Class Abstraction
Overriding a Member of a Class
As mentioned in the previous lesson, when creating a class that would serve as a parent to other classes, to indicate that a member can be overridden in a child class, mark that member with the Overridable keyword. In the child class, you don't have to create a member that corresponds to the overridable member of the parent class. If the child class must have a member of the same name and the same syntax as the overridable member of the parent class, you should override it (if you just create it without overriding, you will receive a warning but the code should work just fine).
To override a member, in the child class, create a member with the same name and the same syntax as the overridable member of the parent class but start it with the Overrides keyword. Then, in the body of the member, create the new behavior you want. Here is an example:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Public Class WorkDay Protected time As Double Protected hSalary As Double Public Sub New(ByVal worktime As Double, ByVal salary As Double) time = worktime hSalary = salary End Sub Public Property TimeWorked As Double Get Return time End Get Set(value As Double) time = value End Set End Property Public Overridable ReadOnly Property RegularTime As Double Get Return TimeWorked End Get End Property Public Overridable ReadOnly Property RegularPay As Double Get Return RegularTime * hSalary End Get End Property End Class Public Class OvertimeWork Inherits WorkDay Public Sub New(ByVal worktime As Double, ByVal salary As Double) MyBase.New(worktime, salary) End Sub Private ReadOnly Property OvertimeSalary Get Return hSalary * 1.50 End Get End Property Public Overrides ReadOnly Property RegularTime As Double Get Return If(time <= 40.00, time, 40.00) End Get End Property Public ReadOnly Property Overtime As Double Get Return If(time <= 40.00, 0.00, time - 40.00) End Get End Property Public Overrides ReadOnly Property RegularPay As Double Get Return RegularTime * hSalary End Get End Property Public ReadOnly Property OvertimePay As Double Get Return OvertimeSalary * Overtime End Get End Property Public ReadOnly Property NetPay As Double Get Return RegularPay + OvertimePay End Get End Property End Class Sub btnCalculateClick(ByVal sender As Object, ByVal e As EventArgs) Dim time As Double Dim salary As Double time = If(String.IsNullOrEmpty(txtTimeWorked.Text), 0.00, CDbl(txtTimeWorked.Text)) salary = If(String.IsNullOrEmpty(txtHourlySalary.Text), 0.00, CDbl(txtHourlySalary.Text)) Dim pay = New OvertimeWork(time, salary) txtRegularTime.Text = FormatNumber(pay.RegularTime) txtOvertime.Text = FormatNumber(pay.Overtime) txtRegularPay.Text = FormatCurrency(pay.RegularPay) txtOvertimePay.Text = FormatCurrency(pay.OvertimePay) txtNetPay.Text = FormatCurrency(pay.NetPay) End Sub </script> <style> #main-title { font-size: 1.08em; font-weight: bold; text-align: center; font-family: Georgia, Garamond, 'Times New Roman', Times, serif; } #central { width: 355px; margin: auto } #tblPayroll { width: 350px; } </style> <title>Employee Payroll Evaluation</title> </head> <body> <form id="frmPayroll" runat="server"> <div id="central"> <p id="main-title">Employee Payroll Evaluation</p> <asp:Table id="tblPayroll" runat="server" BorderColor="#666666" BorderStyle="Double" BorderWidth="2px"> <asp:TableRow runat="server"> <asp:TableCell runat="server" BorderColor="Silver" BorderStyle="Solid" BorderWidth="1pt">Time Worked:</asp:TableCell> <asp:TableCell BorderColor="Silver" BorderStyle="Solid" BorderWidth="1pt" runat="server"> <asp:TextBox ID="txtTimeWorked" runat="server"></asp:TextBox> </asp:TableCell> <asp:TableCell runat="server"></asp:TableCell> </asp:TableRow> <asp:TableRow runat="server"> <asp:TableCell BorderColor="Silver" BorderStyle="Solid" BorderWidth="1pt" runat="server">Hourly Salary:</asp:TableCell> <asp:TableCell BorderColor="Silver" BorderStyle="Solid" BorderWidth="1pt" runat="server"> <asp:TextBox ID="txtHourlySalary" runat="server"></asp:TextBox></asp:TableCell> <asp:TableCell runat="server"> <asp:Button ID="btnCalculate" Text="Calculate" OnClick="btnCalculateClick" runat="server" /> </asp:TableCell> </asp:TableRow> <asp:TableRow runat="server"> <asp:TableCell BorderColor="Silver" BorderStyle="Solid" BorderWidth="1pt" runat="server">Regular Time:</asp:TableCell> <asp:TableCell BorderColor="Silver" BorderStyle="Solid" BorderWidth="1pt" runat="server"> <asp:TextBox ID="txtRegularTime" ReadOnly="true" runat="server"></asp:TextBox></asp:TableCell> <asp:TableCell runat="server"></asp:TableCell> </asp:TableRow> <asp:TableRow runat="server"> <asp:TableCell BorderColor="Silver" BorderStyle="Solid" BorderWidth="1pt" runat="server">Overtime:</asp:TableCell> <asp:TableCell BorderColor="Silver" BorderStyle="Solid" BorderWidth="1pt" runat="server"> <asp:TextBox ID="txtOvertime" ReadOnly="true" runat="server"></asp:TextBox></asp:TableCell> <asp:TableCell runat="server"></asp:TableCell> </asp:TableRow> <asp:TableRow runat="server"> <asp:TableCell BorderColor="Silver" BorderStyle="Solid" BorderWidth="1pt" runat="server">Regular Pay:</asp:TableCell> <asp:TableCell BorderColor="Silver" BorderStyle="Solid" BorderWidth="1pt" runat="server"> <asp:TextBox ID="txtRegularPay" ReadOnly="true" runat="server"></asp:TextBox></asp:TableCell> <asp:TableCell runat="server"></asp:TableCell> </asp:TableRow> <asp:TableRow runat="server"> <asp:TableCell BorderColor="Silver" BorderStyle="Solid" BorderWidth="1pt" runat="server">Overtime Pay:</asp:TableCell> <asp:TableCell BorderColor="Silver" BorderStyle="Solid" BorderWidth="1pt" runat="server"> <asp:TextBox ID="txtOvertimePay" ReadOnly="true" runat="server"></asp:TextBox></asp:TableCell> <asp:TableCell runat="server"></asp:TableCell> </asp:TableRow> <asp:TableRow runat="server"> <asp:TableCell BorderColor="Silver" BorderStyle="Solid" BorderWidth="1pt" runat="server">Net Pay:</asp:TableCell> <asp:TableCell BorderColor="Silver" BorderStyle="Solid" BorderWidth="1pt" runat="server"> <asp:TextBox ID="txtNetPay" ReadOnly="true" runat="server"></asp:TextBox></asp:TableCell> <asp:TableCell runat="server"></asp:TableCell> </asp:TableRow> </asp:Table> </div> </form> </body> </html>
Here is an example of using the webpage:
Introduction to Abstract Classes
A class is referred to as abstract when it is only used to lay a foundation for other classes. In the Microsoft Visual Basic language, to create an abstract class, you must precede its Class keyword with MustInherit. Here is an example:
<script runat="server">
Public MustInherit Class Triangle
End Class
</script>
After creating a class and marking it as MustInherit, you can add and define one or more members to it.
If you create a class and mark it as MustInherit, it is considered incomplete. Because of that, although you can declare a variable of that type, you cannot initialize its instance using the New operator. Consider the following example:
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Public MustInherit Class Triangle
End Class
</script>
<title>Geometry: Isosceles Triangle</title>
</head>
<body>
<div align="center">
<h2>Geometry: Isosceles Triangle</h2>
<%
Dim tri As New Triangle
%>
</body>
</html>
This would produce an error because you cannot use New to instantiate a MustInherit class. This means that, before using a MustInherit class, you must derive a class from it. Here is an example:
<head runat="server">
<script runat="server">
Public MustInherit Class Triangle
End Class
Public Class Isosceles
Inherits Triangle
End Class
</script>
Remember that you cannot apply the New operator to an abstract class to create an object. Instead, you can declare a regular variable using the abstract class, then initialize the variable using the desired inherited class. Here is an example:
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Public MustInherit Class Triangle
End Class
Public Class Isosceles
Inherits Triangle
End Class
</script>
<title>Geometry: Isosceles Triangle</title>
</head>
<body>
<div align="center">
<h2>Geometry: Isosceles Triangle</h2>
<%
Dim tri As Triangle
tri = New Isosceles
%>
</body>
</html>
As an alternative, you can declare the variable using the abstract class and immediately initialize it using an inherited class, on the same line. Here is an example:
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Public MustInherit Class Triangle
End Class
Public Class Isosceles
Inherits Triangle
End Class
</script>
<title>Geometry: Isosceles Triangle</title>
</head>
<body>
<div align="center">
<h2>Geometry: Isosceles Triangle</h2>
<%
Dim tri As Triangle = New Isosceles
%>
</body>
</html>
With the last two techniques, you would have access only to the members of the abstract class. The members, if any, of the inherited class would not be available. The last option is to declare the variable using the inherited class without the abstract class. In this case, the variable can access the public members of the abstract class and those of the inherited class. Here are two examples:
<!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Public MustInherit Class Triangle End Class Public Class Isosceles Inherits Triangle End Class </script> <title>Geometry: Isosceles Triangle</title> </head> <body> <div align="center"> <h2>Geometry: Isosceles Triangle</h2> <% Dim tri As Isosceles tri = New Isosceles Dim iso As Isosceles = New Isosceles %> </body> </html>
An abstract class can have regular members that can be directly accessed by child classes that inherit from the class, or an object created from the child class can access those members. Here are examples:
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Public MustInherit Class Triangle
Private len As Double
Private hgt As Double
Public Property Length As Double
Get
Return len
End Get
Set(ByVal value As Double)
len = value
End Set
End Property
Public Property Height As Double
Get
Return hgt
End Get
Set(ByVal value As Double)
hgt = value
End Set
End Property
Public ReadOnly Property Area As Double
Get
Return Length * Height / 2.0
End Get
End Property
End Class
Public Class Isosceles
Inherits Triangle
End Class
Sub btnCalculateClick(ByVal sender As Object, ByVal e As EventArgs)
Dim length As Double = 0.00
Dim height As Double = 0.00
Dim tri As New Isosceles
If Not String.IsNullOrEmpty(txtLength.Text) Then
length = CDbl(txtLength.Text)
End If
If Not String.IsNullOrEmpty(txtHeight.Text) Then
height = CDbl(txtHeight.Text)
End If
tri.Length = length
tri.Height = height
txtArea.Text = FormatNumber(tri.Area)
End Sub
</script>
<title>Geometry: Isosceles Triangle</title>
</head>
<body>
<div align="center">
<h2>Geometry: Isosceles Triangle</h2>
<form id="frmGeometry" runat="server">
<table>
<tr>
<td>Length:</td>
<td>
<asp:TextBox runat="server"
id="txtLength" Text="0.00"></asp:TextBox></td>
</tr>
<tr>
<td>Height:</td>
<td><asp:TextBox runat="server"
id="txtHeight" Text="0.00"></asp:TextBox>
<asp:Button runat="server" id="btnCalculate"
Text="Calculate"
OnClick="btnCalculateClick"></asp:Button></td>
</tr>
<tr>
<td>Area:</td>
<td><asp:TextBox runat="server"
id="txtArea" Text="0.00"></asp:TextBox></td>
</tr>
</table>
</form>
</div>
</body>
</html>
Here is an example of using the webpage:
The Member Must Be Overridden
When creating a member of an abstract class, you can indicate that the member must be overridden in the class(es). In this case, every class that inherits from the MustInherit class must (also) override that particular member. To indicate this, in the abstract class, the member must be marked, or must preceded, with the MustOverride keyword. Such a member must not be defined in the abstract class. Here is an example:
<script runat="server">
Public MustInherit Class Triangle
Public MustOverride Function CalculatePerimeter() As Double
End Class
</script>
In the same way, you can add as many members as necessary. As a result, you can mark as MustOverride the members that must be overriden and create the other members without MustOverride.
Overriding a Member of an Abstract Class
In a derived class, you must implement each member that is marked as MustOverride from the MustInherit class. You can then use the overriden member. Here is an example:
<!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Public MustInherit Class Triangle Private len As Double Private hgt As Double Public Property Length As Double Get Return len End Get Set(ByVal value As Double) len = value End Set End Property Public Property Height As Double Get Return hgt End Get Set(ByVal value As Double) hgt = value End Set End Property Public ReadOnly Property Area As Double Get Return Length * Height / 2.0 End Get End Property Public MustOverride Function CalculatePerimeter() As Double End Class Public Class Isosceles Inherits Triangle Public Overrides Function CalculatePerimeter() As Double Dim side As Double side = Math.Sqrt((Me.Length * Me.Length) + (Me.Height * Me.Height * 4.00)) / 2.00 Return Me.Length + side + side End Function End Class Sub btnCalculateClick(ByVal sender As Object, ByVal e As EventArgs) Dim length As Double = 0.00 Dim height As Double = 0.00 Dim tri As New Isosceles If Not String.IsNullOrEmpty(txtLength.Text) Then length = CDbl(txtLength.Text) End If If Not String.IsNullOrEmpty(txtHeight.Text) Then height = CDbl(txtHeight.Text) End If tri.Length = length tri.Height = height txtPerimeter.Text = tri.CalculatePerimeter() txtArea.Text = tri.Area End Sub </script> <title>Geometry: Isosceles Triangle</title> </head> <body> <div align="center"> <h2>Geometry: Isosceles Triangle</h2> <form id="frmGeometry" runat="server"> <table> <tr> <td>Length:</td> <td> <asp:TextBox runat="server" id="txtLength" Text="0.00"></asp:TextBox></td> </tr> <tr> <td>Height:</td> <td><asp:TextBox runat="server" id="txtHeight" Text="0.00"></asp:TextBox> <asp:Button runat="server" id="btnCalculate" Text="Calculate" OnClick="btnCalculateClick"></asp:Button></td> </tr> <tr> <td>Perimeter:</td> <td><asp:TextBox runat="server" id="txtPerimeter" Text="0.00"></asp:TextBox></td> </tr> <tr> <td>Area:</td> <td><asp:TextBox runat="server" id="txtArea" Text="0.00"></asp:TextBox></td> </tr> </table> </form> </div> </body> </html>
Here is an example of using the webpage:
In the derived class, you can add new members (properties, methods, and/or constructors) if you judge them necessary. Here are examples:
<!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Public MustInherit Class Triangle Public Property Length As Double Public Property Height As Double Public MustOverride ReadOnly Property Perimeter As Double Public ReadOnly Property Area As Double Get Return Length * Height / 2.0 End Get End Property End Class Public Class Right Inherits Triangle Public Sub New(ByVal length As Double, ByVal height As Double) MyBase.Length = length MyBase.Height = height End Sub Public Overrides ReadOnly Property Perimeter As Double Get Return Me.Length + Me.Height + Math.Sqrt((Me.Length * Me.Length) + (Me.Height * Me.Height)) End Get End Property Public ReadOnly Property Hypotenuse As Double Get Return Math.Sqrt((Me.Length * Me.Length) + (Me.Height * Me.Height)) End Get End Property End Class Sub btnCalculateClick(ByVal sender As Object, ByVal e As EventArgs) Dim length As Double = 0.0 Dim height As Double = 0.0 Dim tri As Right If Not String.IsNullOrEmpty(txtLength.Text) Then length = CDbl(txtLength.Text) End If If Not String.IsNullOrEmpty(txtHeight.Text) Then height = CDbl(txtHeight.Text) End If tri = New Right(length, height) txtHypotenuse.Text = tri.Hypotenuse txtPerimeter.Text = tri.Perimeter txtArea.Text = tri.Area End Sub </script> <title>Geometry: Right Triangle</title> </head> <body> <div align="center"> <h2>Geometry: Right Triangle</h2> <form id="frmGeometry" runat="server"> <table> <tr> <td>Length:</td> <td> <asp:TextBox runat="server" id="txtLength" Text="0.00"></asp:TextBox></td> </tr> <tr> <td>Height:</td> <td><asp:TextBox runat="server" id="txtHeight" Text="0.00"></asp:TextBox> <asp:Button runat="server" id="btnCalculate" Text="Calculate" OnClick="btnCalculateClick"></asp:Button></td> </tr> <tr> <td>Hypotenuse:</td> <td><asp:TextBox runat="server" id="txtHypotenuse" Text="0.00"></asp:TextBox></td> </tr> <tr> <td>Perimeter:</td> <td><asp:TextBox runat="server" id="txtPerimeter" Text="0.00"></asp:TextBox></td> </tr> <tr> <td>Area:</td> <td><asp:TextBox runat="server" id="txtArea" Text="0.00"></asp:TextBox></td> </tr> </table> </form> </div> </body> </html>
Here is an example of using the webpage:
The Relationship Between an Abstract and its Derived Classes
Returning an Object of a Parent Type
A function or a method can return an object based on a abstract class. When creating the function or method, specify its return type as the parent class. Here is an example:
<script runat="server">
Public MustInherit Class Triangle
End Class
Function CreateShape() As Triangle
End Function
</script>
Since you cannot simply create an object of an abstract class and use it directly, you cannot simply return an object of an abstract class from a function. As an alternative, you can declare a variable of a class that inherits from the abstract class and return that object. Then, get the return object where it is needed and use it normally. Here is an example:
<!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Public MustInherit Class Triangle Public Property Length As Double Public Property Height As Double Public MustOverride ReadOnly Property Perimeter As Double Public ReadOnly Property Area As Double Get Return Length * Height / 2.0 End Get End Property End Class Public Class Right Inherits Triangle Public Sub New(ByVal length As Double, ByVal height As Double) MyBase.Length = length MyBase.Height = height End Sub Public Overrides ReadOnly Property Perimeter As Double Get Return Me.Length + Me.Height + Math.Sqrt((Me.Length * Me.Length) + (Me.Height * Me.Height)) End Get End Property Public ReadOnly Property Hypotenuse As Double Get Return Math.Sqrt((Me.Length * Me.Length) + (Me.Height * Me.Height)) End Get End Property End Class Function CreateShape() As Triangle Dim length As Double = 0.0 Dim height As Double = 0.0 Dim shape As Triangle If Not String.IsNullOrEmpty(txtLength.Text) Then length = CDbl(txtLength.Text) End If If Not String.IsNullOrEmpty(txtHeight.Text) Then height = CDbl(txtHeight.Text) End If shape = New Right(length, height) Return shape End Function Sub btnCalculateClick(ByVal sender As Object, ByVal e As EventArgs) Dim tri As Triangle tri = CreateShape() txtPerimeter.Text = tri.Perimeter txtArea.Text = tri.Area End Sub </script> <title>Geometry: Right Triangle</title> </head> <body> <div align="center"> <h2>Geometry: Right Triangle</h2> <form id="frmGeometry" runat="server"> <table> <tr> <td>Length:</td> <td> <asp:TextBox runat="server" id="txtLength" Text="0.00"></asp:TextBox></td> </tr> <tr> <td>Height:</td> <td><asp:TextBox runat="server" id="txtHeight" Text="0.00"></asp:TextBox> <asp:Button runat="server" id="btnCalculate" Text="Calculate" OnClick="btnCalculateClick"></asp:Button></td> </tr> <tr> <td>Perimeter:</td> <td><asp:TextBox runat="server" id="txtPerimeter" Text="0.00"></asp:TextBox></td> </tr> <tr> <td>Area:</td> <td><asp:TextBox runat="server" id="txtArea" Text="0.00"></asp:TextBox></td> </tr> </table> </form> </div> </body> </html>
Here is an example of using the webpage:
The function must return an object based on either the abstract class or of a class that derives from it. If you create a function or a method that returns an abstract class, the resulting object can access only the member of the abstract class.
Passing a Parent Class As Argument
If you are creating a procedure, a function, or a method that receives a class as argument and that class is derived from another, you can pass the parent class as argument. In the body of the procedure, you can access the members of the parent class. Here is an example:
<!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Public MustInherit Class Triangle Public Property Length As Double Public Property Height As Double Public MustOverride ReadOnly Property Perimeter As Double Public ReadOnly Property Area As Double Get Return Length * Height / 2.0 End Get End Property End Class Public Class Right Inherits Triangle Public Sub New(ByVal length As Double, ByVal height As Double) MyBase.Length = length MyBase.Height = height End Sub Public Overrides ReadOnly Property Perimeter As Double Get Return Me.Length + Me.Height + Math.Sqrt((Me.Length * Me.Length) + (Me.Height * Me.Height)) End Get End Property Public ReadOnly Property Hypotenuse() As Double Get Return Math.Sqrt((Me.Length * Me.Length) + (Me.Height * Me.Height)) End Get End Property End Class Function CreateShape() As Triangle Dim length As Double = 0.0 Dim height As Double = 0.0 Dim shape As Triangle If Not String.IsNullOrEmpty(txtLength.Text) Then length = CDbl(txtLength.Text) End If If Not String.IsNullOrEmpty(txtHeight.Text) Then height = CDbl(txtHeight.Text) End If shape = New Right(length, height) Return shape End Function Sub Show(ByVal geo As Triangle) txtPerimeter.Text = geo.Perimeter txtArea.Text = geo.Area End Sub Sub btnCalculateClick(ByVal sender As Object, ByVal e As EventArgs) Dim tri As Triangle tri = CreateShape() Show(tri) End Sub </script> <title>Geometry: Right Triangle</title> </head> <body> <div align="center"> <h2>Geometry: Right Triangle</h2> <form id="frmGeometry" runat="server"> <table> <tr> <td>Length:</td> <td> <asp:TextBox runat="server" id="txtLength" Text="0.00"></asp:TextBox></td> </tr> <tr> <td>Height:</td> <td><asp:TextBox runat="server" id="txtHeight" Text="0.00"></asp:TextBox> <asp:Button runat="server" id="btnCalculate" Text="Calculate" OnClick="btnCalculateClick"></asp:Button></td> </tr> <tr> <td>Perimeter:</td> <td><asp:TextBox runat="server" id="txtPerimeter" Text="0.00"></asp:TextBox></td> </tr> <tr> <td>Area:</td> <td><asp:TextBox runat="server" id="txtArea" Text="0.00"></asp:TextBox></td> </tr> </table> </form> </div> </body> </html>
Once again, remember that you can access only the members of the parent class.
Casting an Object
Casting a value consists of converting it from one type to another. We already know that the Visual Basic language provides tremendous support using conversion functions and the CType() function. When it comes to objects, the conversion is not always smooth because inheritance and abstraction bring new issues. For example, if the CType function cannot perform the conversion, it produces an error. Most of the time, the conversion fails because the value to be converted is not compatible with the target-type. To address issues related to compatibility with objects that may or may not descend from a common class, the Visual Basic language provides a function, actually an operator (in other languages such as C or C++, we call it a macro) named TryCast.
The formula to use the TryCast operator is:
Nothing = TryCast(value, target-type)
Unlike the CType() function, the TryCast operator doesn't convert a value to a specific type. Instead, it checks whether a value is compatible with a target-type and it produces a Boolean value that you can get. Here is an example:
<script runat="server">
Public MustInherit Class Triangle
End Class
Public Class Right
Inherits Triangle
End Class
Sub Show(ByVal geo As Triangle)
Dim result = TryCast(geo, Triangle)
End Sub
</script>
The compatibility is based on inheritance. If the value can be reconciled with the target-type, the TryCast operator indicates that the value is reconciliable with the target-type. If the conversion is not possible, the TryCast operator produces the Nothing. Therefore, when using this operator, you can find out whether it produces Nothing and take appropriate action. Remember (Lesson 12) that that you can check if something is Nothing using the Is operator. Here is an example:
<script runat="server"> Sub Show(ByVal geo As Triangle) Dim result = TryCast(geo, Triangle) If Not result Is Nothing txtPerimeter.Text = geo.Perimeter txtArea.Text = geo.Area End If End Sub </script>
Checking the Type of an Objects
To let you check whether a certain value or an object is of a certain type, the Visual Basic language provides an operator named TypeOf. The formula to use it is:
result = TypeOf value-or-object Is | IsNot type-or-class
The value-or-object can be a variable from a primitive type or a class. It is followed by either Is to check for truthfulness or IsNot to check the contrary. The type-or-class must be a either a known data type or an existing class. The TypeOf operator produces a Boolean value as True if the value-or-object is of type-or-class, or False. Here is an example:
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Public Class Ellipse
Public Property LongRadius() As Double
Public Property ShortRadius As Double
Public Sub New(ByVal a As Double, ByVal b As Double)
LongRadius = a
ShortRadius = b
End Sub
Public ReadOnly Property Area As Double
Get
Return LongRadius * ShortRadius * Math.Pi
End Get
End Property
End Class
Public Class Parallelogram
Public Property Length() As Double
Public Property Side As Double
Public Sub New(ByVal length As Double, ByVal side As Double)
Length = length
Side = side
End Sub
ReadOnly Property Perimeter As Double
Get
Return (Me.Length + Me.Side) * 2.0
End Get
End Property
ReadOnly Property Area As Double
Get
Return Me.Length * Me.Side
End Get
End Property
End Class
Public Sub Present(ByVal shape As Object)
Dim ells As Ellipse
Dim paral As Parallelogram
If TypeOf shape Is Ellipse Then
ells = CType(shape, Ellipse)
txtArea.Text = ells.Area
End If
End Sub
Sub btnCalculateClick(ByVal sender As Object, ByVal e As EventArgs)
Dim len As Double = 0.0
Dim hgt As Double = 0.0
' Dim plate As Ellipse
Dim stadium As Parallelogram
If Not String.IsNullOrEmpty(txtLength.Text) Then
len = CDbl(txtLength.Text)
End If
If Not String.IsNullOrEmpty(txtHeight.Text) Then
hgt = CDbl(txtHeight.Text)
End If
plate = New Ellipse(len, hgt)
Present(plate)
' stadium = New Parallelogram(len, hgt)
' Present(stadium)
End Sub
</script>
<title>Geometric Shape</title>
</head>
<body>
<div align="center">
<h2>Geometric Shape</h2>
<form id="frmGeometry" runat="server">
<table>
<tr>
<td>Length:</td>
<td>
<asp:TextBox runat="server"
id="txtLength" Text="0.00"></asp:TextBox></td>
</tr>
<tr>
<td>Height:</td>
<td><asp:TextBox runat="server"
id="txtHeight" Text="0.00"></asp:TextBox>
<asp:Button runat="server" id="btnCalculate"
Text="Calculate" OnClick="btnCalculateClick"></asp:Button></td>
</tr>
<tr>
<td>Area:</td>
<td><asp:TextBox runat="server"
id="txtArea" Text="0.00"></asp:TextBox></td>
</tr>
<tr>
<td><asp:Label id="lblPerimeter" Text="Perimeter:" Visible="False" runat="server" /></td>
<td><asp:TextBox Visible="False" runat="server"
id="txtPerimeter" Text="0.00"></asp:TextBox></td>
</tr>
</table>
</form>
</div>
</body>
</html>
Shadowing
Introduction
Re-consider the Circle and the Sphere classes from the previous lesson:
<%@ Page Language="VB" %> <!DOCTYPE html> <script runat="server"> Public Class Circle Protected Segment As Double Public Sub New(ByVal radius As Double) Me.Segment = radius End Sub Public Property Radius As Double Get Return Me.Segment End Get Set(ByVal value As Double) Me.Segment = value End Set End Property Public ReadOnly Property Diameter As Double Get Return Me.Segment * 2.0 End Get End Property Public ReadOnly Property Circumference As Double Get Return Me.Diameter * Math.Pi End Get End Property Public ReadOnly Property Area As Double Get Return Me.Segment * Me.Segment * Math.Pi End Get End Property End Class Public Class Sphere Inherits Circle Public Sub New(ByVal radius As Double) MyBase.New(radius) End Sub Public ReadOnly Property Volume As Double Get Return MyBase.Segment * MyBase.Segment * MyBase.Segment * 4.0 * Math.Pi / 3.0 End Get End Property End Class Sub btnCalculateClick(ByVal sender As Object, ByVal e As EventArgs) Dim Area = 0.0 Dim radius = 0.0 Dim disc As Circle Dim Diameter = 0.0 Dim Circumference = 0.0 radius = txtRadius.Text disc = New Circle(radius) txtDiameter.Text = disc.Diameter txtCircumference.Text = disc.Circumference txtArea.Text = disc.Area End Sub </script> <style> #main-title { font-size: 1.08em; font-weight: bold; text-align: center; font-family: Georgia, Garamond, 'Times New Roman', Times, serif; } #whole { margin: auto; width: 205px; } </style> <html> <head runat="server"> <title>Geometry - Circle</title> </head> <body> <p id="main-title">Geometry - Circle</p> <form id="frmGeometry" runat="server"> <div id="whole"> <table> <tr> <td>Radius:</td> <td><asp:TextBox id="txtRadius" Width="75px" runat="server" /></td> </tr> <tr> <td> </td> <td><asp:Button id="btnCalculate" runat="server" Text="Calculate" Width="85px" OnClick="BtnCalculateClick" /> </td> </tr> <tr> <td>Diameter:</td> <td><asp:TextBox id="txtDiameter" runat="server" /></td> </tr> <tr> <td>Circumference:</td> <td><asp:TextBox id="txtCircumference" runat="server" /></td> </tr> <tr> <td>Area:</td> <td><asp:TextBox id="txtArea" runat="server" /></td> </tr> </table> </div> </form> </body> </html>
Here is an example of using the webpage:
As you may know already, both the circle and the sphere have an area but their area are significantly different and the formulas to calculate them are not the same. In the body of the Sphere class, you can simply create a method or a property that calculates the area. Then, when you create an object of the Sphere class, you can access that area. Here is an example:
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Public Class Circle
Protected Segment As Double
Public Sub New(ByVal radius As Double)
Me.Segment = radius
End Sub
Public Property Radius As Double
Get
Return Me.Segment
End Get
Set(ByVal value As Double)
Me.Segment = value
End Set
End Property
Public ReadOnly Property Diameter As Double
Get
Return Me.Segment * 2.0
End Get
End Property
Public ReadOnly Property Circumference As Double
Get
Return Me.Diameter * Math.Pi
End Get
End Property
Public ReadOnly Property Area As Double
Get
Return Me.Segment * Me.Segment * Math.Pi
End Get
End Property
End Class
Public Class Sphere
Inherits Circle
Public Sub New(ByVal radius As Double)
MyBase.New(radius)
End Sub
Public ReadOnly Property Area As Double
Get
Return Me.Segment * Me.Segment * 4.0 * Math.Pi
End Get
End Property
Public ReadOnly Property Volume As Double
Get
Return MyBase.Segment * MyBase.Segment * MyBase.Segment * 4.0 * Math.Pi / 3.0
End Get
End Property
End Class
Sub btnCalculateClick(ByVal sender As Object, ByVal e As EventArgs)
Dim Area = 0.0
Dim radius = 0.0
Dim Volume = 0.0
Dim ball As Sphere
Dim Diameter = 0.0
Dim Circumference = 0.0
radius = txtRadius.Text
ball = New Sphere(radius)
txtDiameter.Text = ball.Diameter
txtCircumference.Text = ball.Circumference
txtArea.Text = ball.Area
txtVolume.Text = ball.Volume
End Sub
</script>
<style>
#main-title
{
font-size: 1.08em;
font-weight: bold;
text-align: center;
font-family: Georgia, Garamond, 'Times New Roman', Times, serif;
}
.tblCircle { width: 200px; }
#whole
{
margin: auto;
width: 205px;
}
</style>
<html>
<head runat="server">
<title>Geometric Volumes - Sphere</title>
</head>
<body>
<p id="main-title">Geometric Volumes - Sphere</p>
<form id="frmGeometry" runat="server">
<div id="whole">
<table class="tblCircle">
<tr>
<td>Radius:</td>
<td><asp:TextBox id="txtRadius" Width="75px" runat="server" /></td>
</tr>
<tr>
<td> </td>
<td><asp:Button id="btnCalculate" runat="server"
Text="Calculate" Width="85px"
OnClick="BtnCalculateClick" />
</td>
</tr>
<tr>
<td>Diameter:</td>
<td><asp:TextBox id="txtDiameter" runat="server" /></td>
</tr>
<tr>
<td>Circumference:</td>
<td><asp:TextBox id="txtCircumference" runat="server" /></td>
</tr>
<tr>
<td>Area:</td>
<td><asp:TextBox id="txtArea" runat="server" /></td>
</tr>
<tr>
<td>volume:</td>
<td><asp:TextBox id="txtVolume" runat="server" /></td>
</tr>
</table>
</div>
</form>
</body>
</html>
Here is an example of using the webpage:
Shadowing a Member of a Class
The code works without any problem and it produces an accurate area of a sphere. If you run that code in a programming environment that can debug code such as Microsoft Visual Studio, you would receive a warning basically asking you whether you are sure of the Area you are trying to access from a Sphere object. If you derive a class a create a member that has the same name and the same access level as a member of the parent class, you must indicate whether the member in the derived class is a new implementation of the member of the same name in the parent class. If that's the case, you must indicate that the member of the derived class "shadows" the member of the parent class. In other words, the member of the child class is a "New" definition.
To indicate that a member of a derived class shadows a member of the parent class, in the child class, precede the name of the member with the Shadows keyword. When doing this, this, there must be a member that has the same name and the same access level as the new member you are creating. Here is an example:
<script runat="server">
Public Class Circle
. . .
Public ReadOnly Property Area As Double
Get
Return Me.Segment * Me.Segment * Math.Pi
End Get
End Property
End Class
Public Class Sphere
Inherits Circle
Public Sub New(ByVal radius As Double)
MyBase.New(radius)
End Sub
Public Shadows ReadOnly Property Area As Double
Get
Return Me.Segment * Me.Segment * 4.0 * Math.Pi
End Get
End Property
Public ReadOnly Property Volume As Double
Get
Return MyBase.Segment * MyBase.Segment * MyBase.Segment * 4.0 * Math.Pi / 3.0
End Get
End Property
End Class
</script>
Inheritance and the .NET Framework
Object: The Ancestor to all Classes
The .NET Framework is the main library used by the Visual Basic programming language. To support this functionality, the .NET Framework provides a rich set of classes (and namespaces).
At the highest level, the library provides the Object class that serves as the common ancestor to all classes used in the .NET Framework. In fact, any time you create a class to use in your Visual Basic project, the class is automatically derived from Object. Consider the following Square class:
<%@ Page Language="VB" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Public Class Square
Private sd As Double
Public Sub New(ByVal side As Double)
Me.sd = side
End Sub
Public ReadOnly Property Side As Double
Get
If sd < 0.00 Then
Return 0.00
Else
Return sd
End If
End Get
End Property
Public ReadOnly Property Perimeter As Double
Get
Return sd * 4.0
End Get
End Property
Public ReadOnly Property Area As Double
Get
Return sd * sd
End Get
End Property
End Class
Sub btnCalculateClick() Handles btnCalculate.Click
Dim plate As Square
Dim side As Double
If String.IsNullOrEmpty(txtSide.Text) Then
side = 0.00
Else
side = CDbl(txtSide.Text)
End If
plate = New Square(side)
txtPerimeter.Text = Format(plate.Perimeter, "standard")
txtArea.Text = Format(plate.Area, "STANDARD")
End Sub
</script>
<style>
#container
{
margin: auto;
width: 305px;
}
#estimation { width: 300px; }
</style>
<title>Geometry - Square</title>
</head>
<body>
<form id="frmGeometry" runat="server">
<div id="container">
<h2>Geometry - Square</h2>
<table id="estimation">
<tr>
<td><b>Side:</b></td>
<td><asp:TextBox id="txtSide" Width="75px" runat="server"></asp:TextBox>
<asp:Button id="btnCalculate" Text="Calculate" runat="server" />
</td>
</tr>
<tr>
<td><b>Perimeter:</b></td>
<td><asp:TextBox id="txtPerimeter" Width="75px"
runat="server"></asp:TextBox></td>
</tr>
<tr><td><b>Area:</b></td>
<td><asp:TextBox id="txtArea" Width="75px"
runat="server"></asp:TextBox></td>
</tr>
</table>
</div>
</form>
</body>
</html>
Here is an example of running the program:
Although the Square class doesn't indicate that it is inheriting from any class, by virtue of belonging to a Visual Basic application, it inherits from Object. For this reason, the above code could also have been written as follows:
<script runat="server">
Public Class Square
Inherits Object
End Class
</script>
This would produce the same results. Most of the time, if not always, you don't need to derive a class from Object: this inheritance is automatic and it is implied. By itself, the Object class provides some useful functionality to its children.
All of the methods of the Object class are public, making them directly available to the descendant classes. For most of them, if you want to use them, you should implement new versions of them in your class.
String Conversion
One of the functionalities provided by the Object class is the ability to convert any object to a string. Because this can mean different things to different classes. The Object class provides a method named ToString. Its syntax is:
Public Overridable Function ToString() As String
In some cases, you can directly call this method as it is available to your class already. Otherwise, most of the time, you will need to indicate how this method should be interpreted by your class, which is done by overriding it. To override this method, follow the rules of overriding a method by associating the Overrides keyword with the syntax of the method. In the body of the method, implement it as you see fit.
Because the Object.ToString() method returns a String object, you can assign its result to a string or pass it to a function or method that takes a string as argument.
Object and Classes Comparisons
Another valuable method of the Object class is called Equals. This method is used to compare two instances of a class for equality. This method is overloaded with two versions and each returns a Boolean value.
One of the versions of the Object.Equals() method has the following syntax:
Overloads Public Overridable Function Equals(ByVal obj As Object) As Boolean
This method can be called by any class of a .NET Framework application and it takes as argument an instance of the class that the called class needs to be compared to. The second version of the Object.Equals() method has the following syntax:
Overloads Public Shared Function Equals(ByVal objA As Object,_ ByVal objB As Object) As Boolean
This version is declared as Shared. This means that it is not called by a specific instance of a class. Instead, it takes two arguments that each represents an instance of the classes that need to be compared.