Generics |
|
Fundamentals of Generics
Introduction to Generic Procedures/Functions
Consider the following sub-procedure:
<script runat="server">
Sub Display(ByVal value As Object)
Response.Write(value)
End Sub
</script>
This procedure takes a value and displays it. Here is an example of calling the procedure:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head> <script runat="server"> Sub Display(ByVal value As Object) Response.Write(value) End Sub </script> <title>Exercise</title> </head> <body> <% Dim a = 25 Display(a) %> </body> </html>
This would produce:
Here is another example of calling the same procedure:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head> <script runat="server"> Sub Display(ByVal value As Object) Response.Write(value) End Sub </script> <title>Exercise</title> </head> <body> <% Dim m = "Social Sciences: Philosophy" Display(m) %> </body> </html>
This would produce:
The procedure doesn't restrict the type of value it can receive. This means that any value can be passed to the procedure/function. A generic procedure/function is one that involves one or more parameters without specifying the exact type of value the parameter(s) is(are) using but still carrying its(their) normal operation(s). Normally, at the time the procedure is created, it specifies its operation(s) or role(s) but doesn't restrict it(them) to one particular type. Only when the function is called is(are) the desired type(s) specified.
Creating a Generic Procedure or Function
A generic procedure or function must always take a (or at least one) parameter. When creating the procedure or function, to indicate that its parameter is not specified, in other words, to indicate that it is generic, specify it using the Of keyword followed by a letter or a word. The formula to follow is:
[ access-modifier(s) ] [ Shadows ] [ Sub | Function name(Of letter/word)(ByVal arg As letter/word)
Start by specifying which one of the sub-procedure or the function you want to create. This is followed by a name and two sets of parentheses. In the first set, use the Of keyword followed by a letter or a word, any letter or any non-keyword word. This is followed by a second set of parentheses in which you pass a parameter of the same letter or word of the first set of parentheses. Here is an example:
<script runat="server">
Sub Display(Of Something)(ByVal parameter As Something)
End Sub
</script>
Calling a Generic Procedure or Function
To call a generic procedure, simply pass the desired argument to it. Here is an example of calling the procedure by passing a number-based type:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script Language="VB" runat="server"> Public Sub Display(Of Something)(ByVal parameter As Something) Response.Write(parameter.ToString()) End Sub </script> <title>Exercise</title> </head> <body> <% Dim m = 1245.50 Display(m) %> </body> </html>
This would produce:
Here is another example of calling the same procedure passing an object:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Public Class Element Public AtomicNumber As Integer Public ChemicalSymbol As String Public ElementName As String Public AtomicMass As String Public Phase As String Public Appearance As String Public Introduction As String Public Conclusion As String Public Overrides Function ToString$() return Me.Introduction & Environment.NewLine & "<p>" & ElementName & " has the following properties:</p>" & Environment.NewLine & "<ul>" & Environment.NewLine & " <li>Chemical Symbol: " & ChemicalSymbol & "</li>" & Environment.NewLine & " <li>Atomic Number: " & AtomicNumber & "</li>" & Environment.NewLine & " <li>Atomic Weight: " & AtomicMass & "</li>" & Environment.NewLine & " <li>Phase: " & Phase & "</li>" & Environment.NewLine & " <li>Appearance: " & Appearance & "</li>" & Environment.NewLine & "</ul>" & Environment.NewLine & Me.Conclusion End Function End Class Public Sub Display(Of Something)(ByVal parameter As Something) Response.Write(parameter.ToString()) End Sub </script> <title>Exercise</title> </head> <body> <% Dim c As Element = New Element c.Conclusion = "<p>While hydrogen is the dominant substance in the universe, carbon is " & "the main component of most minerals such as diamond and graphite. Combining " & "hydrogen and carbon results in many types of organic compounds.</p>" c.Introduction = "<p>Carbon is one of the most commonly found chemical components on earth. It " & "can be found inside the earth, on the human body, and in many organic compounds. " & "Carbon is the 6th most abundant chemical element on earth. The order of " & "abundance is:</p>" c.AtomicNumber = 6 c.ChemicalSymbol = "C" c.ElementName = "Carbon" c.AtomicMass = 12.011 c.Phase = "Solid" c.Appearance = "Black" Display(c) %> </body> </html>
This would produce:
By tradition, the letter t (or T) is used for the Of parameter. Here is an example:
<%@ Page Language="VB" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Public Sub Display(Of t)(ByVal parameter As t)
Response.Write(parameter.ToString())
End Sub
</script>
<title>Exercise</title>
</head>
<body>
<%
Dim age As Integer
Dim drinkingUnderAge As Boolean
age = 21
drinkingUnderAge = (age >= 21)
Display(drinkingUnderAge )
%>
</body>
</html>
This would produce:
A Procedure With Generic and Non-Generic Types
You can create a procedure or a function that uses a generic parameter and one or more parameters with (a) specific data type(s). Here is an example:
Public Sub Display(Of t)(ByVal m As String, ByVal arg As t) End Sub
When calling the procedure, pass the arguments in the appropriate order and the right type. Here is an example:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Public Enum HouseTypes Condominium Townhouse SingleFamily End Enum Public Sub Display(Of t)(ByVal m As String, ByVal arg As t) Response.Write(arg.ToString() & "<br>" & m) End Sub </script> <title>Exercise</title> </head> <body> <% Dim category As HouseTypes = HouseTypes.SingleFamily Dim description = "A single-family is a type of house that stands by itself. That is, it is not attached to another house." Display(description, category) Response.Write("<br>") Response.Write("<br>") Dim pi = 3.14156 Dim descr = "The greek letter PI is used to calculate the area of a circle and related geometric figures such as the sphere." Display(descr, pi) %> </body> </html>
This would produce:
Passing Many Arguments to a Generic Procedure
A generic procedure can take more than one argument. When creating the procedure, if the parameters will use the same type, each parameter must use the common type specified in the first set of parentheses. In the second set of parentheses, specify each parameter but separate them with commas. Here is an example:
Public Sub Display(Of t)(ByVal a As t, ByVal b As t)
End Sub
When calling the procedure, pass the appropriate number of arguments and they must be of the same type. Here is an example:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Public Sub Display(Of u)(ByVal a As u, ByVal b As u) Response.Write(a.ToString() & ", " & b.ToString()) End Sub </script> <title>Exercise</title> </head> <body> <% Dim t As Boolean Dim f As Boolean t = True f = False Response.Write("Boolean Values: ") Display(t, f) %> </body> </html>
This would produce:
Here is another example of calling the same procedure:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Public Sub Display(Of u)(ByVal a As u, ByVal b As u) Response.Write(a.ToString() & "<br>" & b.ToString()) End Sub </script> <title>Exercise</title> </head> <body> <% Dim linguistics = "<h3>Linguistics</h3>" & "<p>Linguistics is the study of one or a family of languages. " & "Linguistics studies the science, the technology, the mechanical, and physical " & "aspects that rule a language. Linguistics scientifically describes the sound (and " & "justifies the creation of the sound) produced when a particular " & "language is spoken, how, and usually why a certain sound is produced.</p>" Dim anthropology = "<h3>Biology</h3>" & "<p>Biology is the study of the existence of living " & "organisms. Biology studies how the organisms start (such as how an organism " & "is born), how they grow (or how they change from one state or phase to " & "another), how they live, how they function, where they dwell, and how their " & "existence ends (such as how they die). Biology can be divided in various " & "fields of studies.</p>" Display(linguistics, anthropology) %> </body> </html>
This would produce:
Here is another example of calling the same procedure:
<%@ Page Language="VB" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Public Sub Display(Of u)(ByVal a As u, ByVal b As u)
Response.Write(a.ToString() & " : " & b.ToString())
End Sub
</script>
<title>Exercise</title>
</head>
<body>
<%
Dim ratio1 = 5
Dim ratio2 = 3
Response.Write("We need to distribute 6500 in the ratio ")
Display(ratio1, ratio2)
%>
</body>
</html>
This would produce:
If the arguments must be of different types, when creating the procedure or function, in the first set of parentheses, after the Of keyword, use different letters or words separated by commas. Use the same letters or words in the same order in the second set of parentheses for the parameters. Here is an example:
<%@ Page Language="VB" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Public Sub Display(Of u, v)(ByVal a As u, ByVal b As v)
Response.Write(a.ToString() & ": " & b.ToString())
End Sub
</script>
<title>Exercise</title>
</head>
<body>
<%
Dim m = "Long Sleeve Shirt"
Dim n = 108.95
Display(m, n)
%>
</body>
</html>
This would produce:
Here is another example of calling the same procedure:
<%@ Page Language="VB" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Public Sub Display(Of u, v)(ByVal a As u, ByVal b As v)
Response.Write(a.ToString() & ": " & b.ToString())
End Sub
</script>
<title>Exercise</title>
</head>
<body>
<%
Dim t = True
Dim o = 1
Display(t, o)
%>
</body>
</html>
This would produce:
In the same way, you can create a generic procedure with as many parameters as you want. You can also create a procedure or function that takes a combination of generic and non-generic parameters.
Generic Classes
Introduction
A class can have one or more members whose type(s) is(are) not known at the time the class is created. This is typical for a class that would be used to create a list. That is, you may want to create a list-based class (also called a collection class) that can be used to create lists of any types.
A generic class is one whose main member (property) type is not known in advance.
Creating a Generic Class
To create a generic class, add some parentheses after the name of the class. In the parentheses, type Of followed by a letter or a word. Here is an example:
<script runat="server">
Class Occurrence(Of t)
End Class
</script>
You can then add the necessary members, such as a default constructor (a constructor with empty parentheses), properties and methods. Here are examples:
<script runat="server">
Class Occurrence(Of t)
Public Sub New()
End Sub
Public Sub Remember()
My.Response.Write("This is a generic class.")
End Sub
End Class
</script>
Creating an Object From a Generic Class
When creating an object from a generic class, if you have a default constructor, you must add the parentheses to the name of the class applied to the New operator. Even if the class doesn't have a default constructor, you must add empty parentheses to the name of the class. In the parentheses, type Of followed by the type of the value you are planning to use. You can then use the object to access the members of the class. Here is an example:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Class Occurrence(Of t) Public Sub Remember() My.Response.Write("This is a generic class.") End Sub End Class </script> <title>Exercise</title> </head> <body> <% Dim incremental As New Occurrence(Of Integer) Dim period As New Occurrence(Of String) Dim national As New Occurrence(Of Date) incremental.Remember() Response.Write("<br>") period.Remember() %> </body> </html>
This would produce:
A Generic Field
A generic field is a member variable that uses the letter or the word of the Of clause as its type. Here is an example:
<script runat="server">
Class Occurrence(Of t)
' A generic field
Private gen As t
End Class
</script>
Such a field can be accessed by any member of the class, whether the member indicates that it uses the generic type or not. Here is an example:
<script runat="server">
Class Occurrence(Of t)
' A generic field
Private gen As t
Public Sub Relate()
My.Response.Write(gen.ToString())
End Sub
End Class
</script>
A Generic Property
A property is generic if it uses the letter or the word of the Of clause as its type. If the property auto-implements, there is no further action you need to take. For a read-write property, you should first create a field of the same type and use that field in your property. You can then use the property like any other. Here is an example:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Class Occurrence(Of t) ' A generic field Private gen As t ' A generic property Public Property Occurs As t Get Return gen End Get Set(ByVal value As t) gen = value End Set End Property Public Sub Relate() My.Response.Write(gen.ToString()) End Sub End Class </script> <title>Exercise</title> </head> <body> <% Dim incremental As New Occurrence(Of Integer) Dim period As New Occurrence(Of String) Dim national As New Occurrence(Of Date) incremental.Occurs = 1 Response.Write("First day of every month: ") incremental.Relate() Response.Write("<br>") period.Occurs = "01/01/1901" Response.Write("Australia Independence: ") period.Relate() Response.Write("<br>") national.Occurs = New DateTime(1975, 11, 11) Response.Write("Angola National Day: ") national.Relate() %> </body> </html>
This would produce:
A Generic Method
A method or a constructor of a class can be generic. When creating the method, pass one or more parameter that use the letter or the word of the Of keyword as parameter. Other than that, follow the normal rules for procedures. Here are examples:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Class Occurrence(Of t) ' A generic field Private gen As t Public Sub New() End Sub Public Sub New(ByVal arg As t) Me.gen = arg End Sub Public Sub Relate() My.Response.Write(gen.ToString()) End Sub Public Sub Relate(ByVal a As t, ByVal b As t) My.Response.Write(a.ToString() & " at " & b.ToString()) End Sub End Class </script> <title>Exercise</title> </head> <body> <% Dim days As New Occurrence(Of Integer)(30) Dim war As New Occurrence(Of String) Response.Write("The months of April, Juin, September, and November have ") days.Relate() Response.Write(" days.") Response.Write("<br>The attack on Pearl Harbor started on ") war.Relate("07/12/1941", "07:48 AM") Response.Write(" local time.") %> </body> </html>
This would produce:
A Generic Class With Various Types
As seen with procedures, a generic class can use different generic types. To specify those types, in the parentheses of creating the class, type Of followed by a letter or a word for each type of value but seperate them with commas. Here is an example:
<script runat="server">
Class Combination(Of u, v)
End Class
</script>
When creating an object from the class, in the parentheses of the name of the class, type Of followed by each type but separate them with commas. Here is an example:
<%@ Page Language="VB" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Class Combination(Of u, v)
End Class
</script>
<title>Exercise</title>
</head>
<body>
<%
Dim combo As New Combination(Of Integer, String)
%>
</body>
</html>
In the body of the class, you don't have to use any of the types. In fact, you may decide to use only one of them. In this case, create the members that would need a value for that type. If you create a constructor uses only one of the types, when declaring a variable, add a set of parentheses to the class on the variable and add the value for the type. Here is an example:
<%@ Page Language="VB" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Class Combination(Of u, v)
Private intro As u
Private define As v
Public Sub New(ByVal a As u)
Me.intro = a
End Sub
Public Property Introduction As u
Get
Return intro
End Get
Set(ByVal value As u)
intro = value
End Set
End Property
Public Sub Relate()
My.Response.Write(intro.ToString())
End Sub
End Class
</script>
<title>Exercise</title>
</head>
<body>
<%
Dim midday As New Combination(Of Integer, String)(12)
Response.Write("Midday is at ")
midday.Relate()
%>
</body>
</html>
This would produce:
Otherwise, you can use all types specified in the Of clause. Here are examples:
<%@ Page Language="VB" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Class Combination(Of u, v) Private intro As u Private define As v Public Sub New() End Sub Public Sub New(ByVal a As u, ByVal b As v) Me.intro = a Me.define = b End Sub Public Property Introduction() As u Get Return intro End Get Set(ByVal value As u) intro = value End Set End Property Public Property Definition() As v Get Return define End Get Set(ByVal value As v) define = value End Set End Property Public Sub Show() My.Response.Write(intro.ToString() & ", " & define.ToString()) End Sub Public Sub Show(ByVal a As u, ByVal b As v) My.Response.Write(a.ToString() & ", " & b.ToString()) End Sub End Class </script> <title>Exercise</title> </head> <body> <% Dim war As New Combination(Of String, Date) war.Introduction = "World War II" war.Definition = New DateTime(1939, 09, 01) Response.Write("Event: ") war.Show() Dim values As New Combination(Of Integer, Boolean)() Response.Write("<br>Some values: ") values .Show(40, False) Dim employee As New Combination(Of Integer, String)(826048, "James Brauer") Dim work As New Combination(Of Date, Double)(New DateTime(2017, 6, 10), 9.50) Response.Write("<p>Employee: ") employee.Show() Response.Write("<br>Work Day: ") work.Show() Response.Write("</p>") %> </body> </html>
This would produce:
All of the generic procedures and classes we have used so far could take any type. In some cases, when creating a generic function or a generic class, you may want to restrict the types of values that can be used on the generic parameter. Putting a restriction on a generic parameter is referred to as constraining the generic type. Generic constraining is done using the As keyword.
To indicate that a parameter type of a generic procedure/function or a generic class must be based on a certain type, after the letter or word of the Of clause, add As followed by the desired type. In the body of the generic procedure or generic class, use the parameter based on the rules of its restricted type. Here is an example:
<%@ Page Language="VB" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Public Class Numeric
Private oper1 As Double
Private oper2 As Double
Public Sub New(ByVal a As Double, ByVal b As Double)
oper1 = a
oper2 = b
End Sub
Public Function Add()
Return oper1 + oper2
End Function
Public Function Multiply()
Return oper1 * oper2
End Function
Public Function Subtract()
Return oper1 - oper2
End Function
Public Function Divide()
If oper2 = 0 Then
Return 0
Else
Return oper1 / oper2
End If
End Function
End Class
Public Sub Display(Of t As Numeric)(ByVal parameter As t)
Response.Write(parameter.Add())
End Sub
</script>
<title>Exercise</title>
</head>
<body>
<%
Dim number As New Numeric(1560, 280)
Response.Write("1560 + 280 = ")
Display(number)
%>
</body>
</html>
This would produce:
|
||
Previous | Copyright © 2014-2016, FunctionX | Next |
|