Home

Int

Interfaces Fundamentals

Introduction

Creating an Interface

The basic formula to create an interface is:

[ access-modifier(s) ] [ Shadows ] Interface name
    members
End Interface

You:

This would produce:

<script runat="server">
Interface IPolygon

End Interface
</script>

Here is an example:

OuterXml

New. Here is an example:

let
xaItemNumber

:

Affiche

Notice that, in both cases, the newly added element is empty.

As you might have realized, it is very easy to create an element. This is done in two simple steps:

<road />

Introduction

As.


This time, the result is:

Shadows keyword if necessary.Public, Protected, Overrides, MustOverride, and Overridable.

:

When implementing the method in a class, use the following formula;



This would produce:

Adding a Procedure to an Interface

When implementing the function in the body of the class, make sure you return the propriate type of value. Here is an example:

For Each XmlNodeList XmlNode ChildNodes. Here is an example:

as follows:



)

Here is an example:



AppendChild(). Here is an example:

This would produce:




This would produce:

Video Collection

Item:

. Here are examples:

.Item(3)

Based on the videos.xml file we had earlier, this would produce:

Locating an Element Using its Name Locating an Element Using its Name

This would produce:

Locating an Element Using a Tag Name

This would produce:

Locating an Element Using a Tag Name

This would produce:

Locating an Element Using a Tag Name

This would produce:

Locating an Element Using a Tag Name

Here is an example of calling the method:



lvwRoads.ItemSelectionChanged.Add lvwRoadsItemSelectionChanged

This would produce:

Locating an Element Using its Index

This would produce:

Locating an Element Using its Index


xnRoad.FirstChild.NextSibling.NextSibling.InnerText |> ignore // Distance
xnRoad.FirstChild.NextSibling.NextSibling.NextSibling

This would produce:

The Siblings of a Node

As. Here is an example:

.FirstChild

This would produce:

Video Collection

This would produce:

Video Collection

This would produce:

A Function as a Member of an Interface

A Property in an Interface

An interface can contain one or more properties. If a property is intended to be read-write, the formula to create it is:

Property property-name As data-type
for child in xnlVideos do
child

This would produce:

Video Collection

When implementing the property in a class, end its first line with Implements, a period, and the name of the property. Here is an example:

<%@ Page Language="VB" %>

<!DOCTYPE html>

<script runat="server">
Public Interface IPolygon
    Property Side As Double
End Interface

Public Class Triangle
    Implements IPolygon

    Protected Edge As Double

    Public Sub New(ByVal side As Double)
        Me.Edge = side
    End Sub

    Public Property Side() As Double Implements IPolygon.Side
        Get
            Return Me.Edge
        End Get
        Set(ByVal value As Double)
            Me.Edge = value
        End Set
    End Property
End Class
</script>
<html>
<head runat="server">
<title>Geometry - Polygons: The Equilateral Triangle</title>
</head>
<body>
<h5>Geometry - Polygons: The Equilateral Triangle</h5>

<%
    Dim length As Double = 248.97
    Dim equilateral As Triangle

    equilateral = New Triangle(length)

    Response.Write("<p>Side: " & equilateral.Side & "</p>")
%>
</body>
</html>

This would produce:

A Property in an Interface

If the property is intended to be read-only, the formula to create it is:

ReadOnly Property name Get

Notice that you must start with the ReadOnly keyword and end with Get. When implementing the property, at the end of the first line, omit Get to use it in the body of the property. Here are two examples:

<%@ Page Language="VB" %>

<!DOCTYPE html>

<script runat="server">
Public Interface IPolygon
    Property Side As Double
    ReadOnly Property Perimeter As Double
    ReadOnly Property Area As Double
End Interface

Public Class Triangle
    Implements IPolygon

    Protected Edge As Double

    Public Sub New(ByVal side As Double)
        Me.Edge = side
    End Sub

    Public Property Side() As Double Implements IPolygon.Side
        Get
            Return Me.Edge
        End Get
        Set(ByVal value As Double)
            Me.Edge = value
        End Set
    End Property

    Public ReadOnly Property Perimeter() As Double Implements IPolygon.Perimeter
        Get
            Return Me.Side * 3.0
        End Get
    End Property

    Public ReadOnly Property Area() As Double Implements IPolygon.Area
        Get
            Return Me.Side * Me.Side * Math.Sqrt(3.0) / 4.0
        End Get
    End Property
End Class

Sub btnCalculateClick(ByVal sender As Object, ByVal e As EventArgs)
    Dim Area = 0.0
    Dim side = 0.0
    Dim perimeter = 0.0
    Dim equilateral As Triangle
    
    If Not String.IsNullOrEmpty(txtSide.Text) Then
        side = CDbl(txtSide.Text)
    End If

    equilateral = New Triangle(side)

    txtArea.Text = equilateral.Area
    txtPerimeter.Text = equilateral.Perimeter
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 - Polygons: The Equilateral Triangle</title>
</head>
<body>
<p id="main-title">Geometry - Polygons: The Equilateral Triangle</p>
<form id="frmGeometry" runat="server">
<div id="whole">
 
<table>
  <tr>
    <td>Side:</td>
    <td><asp:TextBox id="txtSide" Width="75px" runat="server" /></td>
    </tr>
  <tr>
      <td>&nbsp;</td>
      <td><asp:Button id="btnCalculate" runat="server"
                      Text="Calculate" Width="85px"
                      OnClick="BtnCalculateClick" />
      </td>
  </tr>
    <tr>
      <td>Perimeter:</td>
      <td><asp:TextBox id="txtPerimeter" 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:

A Property in an Interface

Here is an example of using the webpage:

A Property in an Interface

Here is an example of using the webpage:

A Property in an Interface

If the property is intended to be write-only, the formula to create it is:

WriteOnly Property name Set

Other than that, you can create as many classes as you want and that implement an interface of your choice. Here is an example:

<%@ Page Language="VB" %>

<!DOCTYPE html>

<script runat="server">
Public Interface IPolygon
        Property Side As Double
        ReadOnly Property Perimeter As Double
        ReadOnly Property Area As Double
End Interface

Public Class Hexagon
        Implements IPolygon

        Protected Edge As Double

        Public Sub New(ByVal side As Double)
            Me.Edge = side
        End Sub

        Public Property Side() As Double Implements IPolygon.Side
            Get
                Return Me.Edge
            End Get
            Set(ByVal value As Double)
                Me.Edge = value
            End Set
        End Property

        ReadOnly Property Perimeter() As Double Implements IPolygon.Perimeter
            Get
                Return Me.Side * 6.0
            End Get
        End Property

        ReadOnly Property Area() As Double Implements IPolygon.Area
            Get
                Return Me.Side * Me.Side * Math.Sqrt(3.0) * 3.0 / 2.0
            End Get
        End Property
End Class

Sub btnCalculateClick(ByVal sender As Object, ByVal e As EventArgs)
        Dim side = 0.0
        Dim Area = 0.0
        Dim perimeter = 0.0
        Dim figure As Hexagon

        If Not String.IsNullOrEmpty(txtSide.Text) Then
            side = CDbl(txtSide.Text)
        End If

        figure = New Hexagon(side)

        txtArea.Text = figure.Area
        txtPerimeter.Text = figure.Perimeter
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 - Polygons: The Hexagon</title>
</head>
<body>
<p id="main-title">Geometry - Polygons: The Hexagon</p>
<form id="frmGeometry" runat="server">
<div id="whole">
 
<table>
  <tr>
    <td>Side:</td>
    <td><asp:TextBox id="txtSide" Width="75px" runat="server" /></td>
    </tr>
  <tr>
      <td>&nbsp;</td>
      <td><asp:Button id="btnCalculate" runat="server"
                      Text="Calculate" Width="85px"
                      OnClick="BtnCalculateClick" />
      </td>
  </tr>
    <tr>
      <td>Perimeter:</td>
      <td><asp:TextBox id="txtPerimeter" runat="server" /></td>
    </tr>
  <tr>
    <td>Area:</td>
    <td><asp:TextBox id="txtArea" runat="server" /></td>
  </tr>
</table>
</div>
</form>
</body>
</html>

Consider the following XML file named videos.xml:

Locating an Element Using its Index

Here is an example of using the webpage:

A Property in an Interface

You can also add new members to the classes, members that are not related to the interface. Here are examples:

<%@ Page Language="VB" %>

<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Interface IPolygon
    Property Side As Double
    ReadOnly Property Perimeter As Double
    ReadOnly Property Area As Double
End Interface

Public Class Triangle
    Implements IPolygon

    Protected Edge As Double

    Public Sub New(ByVal side As Double)
        Me.Edge = side
    End Sub

    Public Property Side As Double Implements IPolygon.Side
        Get
            Return Me.Edge
        End Get
        Set(ByVal value As Double)
            Me.Edge = value
        End Set
    End Property

    Public ReadOnly Property Height As Double
        Get
            Return Me.Edge * Math.Sqrt(3.0) / 2.0
        End Get
    End Property

    Public ReadOnly Property Perimeter As Double Implements IPolygon.Perimeter
        Get
            Return Me.Side * 3.0
        End Get
    End Property

    ReadOnly Property Area As Double Implements IPolygon.Area
        Get
            Return Me.Side * Me.Side * Math.Sqrt(3.0) / 4.0
        End Get
    End Property

    ReadOnly Property RadiusOfCircumscribedCircle As Double
        Get
            Return Me.Edge / Math.Sqrt(3.0)
        End Get
    End Property

    ' Also called Apothem
    ReadOnly Property RadiusOfInscribedCircle As Double
        Get
            Return Me.Edge * Math.Sqrt(3.0) / 6.0
        End Get
    End Property
End Class

Public Class Square
    Implements IPolygon

    Protected Edge As Double

    Public Sub New(ByVal side As Double)
        Me.Edge = side
    End Sub

    Public Property Side As Double Implements IPolygon.Side
        Get
            Return Me.Edge
        End Get
        Set(ByVal value As Double)
            Me.Edge = value
        End Set
    End Property

    Public ReadOnly Property Diagonal As Double
        Get
            Return Me.Side * Math.Sqrt(2.0)
        End Get
    End Property

    ReadOnly Property Perimeter As Double Implements IPolygon.Perimeter
        Get
            Return Me.Side * 4.0
        End Get
    End Property

    ReadOnly Property Area As Double Implements IPolygon.Area
        Get
            Return Me.Side * Me.Side
        End Get
    End Property
End Class

Public Class Pentagon
    Implements IPolygon

    Protected Edge As Double

    Public Sub New(ByVal side As Double)
        Me.Edge = side
    End Sub

    Public Property Side As Double Implements IPolygon.Side
        Get
            Return Me.Edge
        End Get
        Set(ByVal value As Double)
            Me.Edge = value
        End Set
    End Property

    Public ReadOnly Property Height As Double
        Get
            Return Me.Edge * Math.Sqrt(5.0 + (2.0 * Math.Sqrt(5))) / 2.0
        End Get
    End Property

    Public ReadOnly Property Diagonal As Double
        Get
            Return Me.Side * ((1 + Math.Sqrt(5.0)) / 2.0)
        End Get
    End Property

    ReadOnly Property Perimeter As Double Implements IPolygon.Perimeter
        Get
            Return Me.Side * 5.0
        End Get
    End Property

    ReadOnly Property Area As Double Implements IPolygon.Area
        Get
            Return Me.Side * Me.Side * Math.Sqrt(5.0 * (5 + (2 * Math.Sqrt(5.0)))) / 4.0
        End Get
    End Property
End Class

Public Class Hexagon
    Implements IPolygon

    Protected Edge As Double

    Public Sub New(ByVal side As Double)
        Me.Edge = side
    End Sub

    Public Property Side As Double Implements IPolygon.Side
        Get
            Return Me.Edge
        End Get
        Set(ByVal value As Double)
            Me.Edge = value
        End Set
    End Property

    ReadOnly Property Perimeter As Double Implements IPolygon.Perimeter
        Get
            Return Me.Side * 6.0
        End Get
    End Property

    ReadOnly Property Area As Double Implements IPolygon.Area
        Get
            Return Me.Side * Me.Side * Math.Sqrt(3.0) * 3.0 / 2.0
        End Get
    End Property
End Class

Public Class Octagon
    Implements IPolygon

    Protected Edge As Double

    Public Sub New(ByVal side As Double)
        Me.Edge = side
    End Sub

    Public Property Side As Double Implements IPolygon.Side
        Get
            Return Me.Edge
        End Get
        Set(ByVal value As Double)
            Me.Edge = value
        End Set
    End Property

    ReadOnly Property Perimeter As Double Implements IPolygon.Perimeter
        Get
            Return Me.Side * 8.0
        End Get
    End Property

    ReadOnly Property Area As Double Implements IPolygon.Area
        Get
            Return Me.Side * Me.Side * 2.0 * (1 + Math.Sqrt(2.0))
        End Get
    End Property
End Class

Sub btnCalculateClick(ByVal sender As Object, ByVal e As EventArgs)
    Dim side = 0.0
    Dim equilateral As Triangle
    
    If Not String.IsNullOrEmpty(txtSide.Text) Then
        side = CDbl(txtSide.Text)
    End If

    equilateral = New Triangle(side)

    txtHeight.Text = equilateral.Height
    txtPerimeter.Text = equilateral.Perimeter
    txtArea.Text = equilateral.Area
    txtRadiusOfCircumscribedCircle.Text = equilateral.RadiusOfCircumscribedCircle
    txtRadiusOfInscribedCircle.Text = equilateral.RadiusOfInscribedCircle
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:  305px;
}
</style>
<title>Geometry - Polygons: The Equilateral Triangle</title>
</head>
<body>
<p id="main-title">Geometry - Polygons: The Equilateral Triangle</p>
<form id="frmGeometry" runat="server">
<div id="whole">
 
<table>
  <tr>
    <td>Side:</td>
    <td><asp:TextBox id="txtSide" Width="75px" runat="server" /></td>
    </tr>
  <tr>
      <td>&nbsp;</td>
      <td><asp:Button id="btnCalculate" runat="server"
                                Text="Calculate" Width="85px"
                                OnClick="BtnCalculateClick" />
      </td>
  </tr>
    <tr>
      <td>Height:</td>
      <td><asp:TextBox id="txtHeight" runat="server" /></td>
    </tr>
    <tr>
      <td>Perimeter:</td>
      <td><asp:TextBox id="txtPerimeter" runat="server" /></td>
    </tr>
  <tr>
    <td>Area:</td>
    <td><asp:TextBox id="txtArea" runat="server" /></td>
  </tr>
    <tr>
      <td>Radius of Circumscribed Circle:</td>
      <td><asp:TextBox id="txtRadiusOfCircumscribedCircle" runat="server" /></td>
    </tr>
  <tr>
    <td>Radius of Inscribed Circle:</td>
    <td><asp:TextBox id="txtRadiusOfInscribedCircle" runat="server" /></td>
  </tr>
</table>
</div>
</form>
</body>
</html>

Here is an example of using the webpage:

A Property in an Interface

Primary Options on Using an Interface

Declaring a Variable of Interface Type

You cannot declare a variable of an interface and use it directly as you would a class. On the othe hand, you can declare a variable by using the name of the interface but not allocate memory for the variable. Here is an example:

<%@ Page Language="VB" %>

<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Interface IPolygon
    Property Side As Double
    ReadOnly Property Perimeter As Double
    ReadOnly Property Area As Double
End Interface
</script>
<title>Geometry - Polygons</title>
</head>
<body>
<%
    Dim figure As IPolygon
%>
</body>
</html>

When allocating memory for the object using the New operator, you must use a class that implements that interface. After that, you can use the object. Here is an example:

<%@ Page Language="VB" %>

<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Interface IPolygon
    Property Side As Double
    ReadOnly Property Perimeter As Double
    ReadOnly Property Area As Double
End Interface

Public Class Square
    Implements IPolygon

    Protected Edge As Double

    Public Sub New(ByVal side As Double)
        Me.Edge = side
    End Sub

    Public Property Side As Double Implements IPolygon.Side
        Get
            Return Me.Edge
        End Get
        Set(ByVal value As Double)
            Me.Edge = value
        End Set
    End Property

    Public ReadOnly Property Diagonal As Double
        Get
            Return Me.Side * Math.Sqrt(2.00)
        End Get
    End Property

    ReadOnly Property Perimeter As Double Implements IPolygon.Perimeter
        Get
            Return Me.Side * 4.0
        End Get
    End Property

    ReadOnly Property Area As Double Implements IPolygon.Area
        Get
            Return Me.Side * Me.Side
        End Get
    End Property
End Class

Sub btnCalculateClick(ByVal sender As Object, ByVal e As EventArgs)
    Dim side = 0.0
    Dim plate As IPolygon
    
    If Not String.IsNullOrEmpty(txtSide.Text) Then
        side = CDbl(txtSide.Text)
    End If

    plate = New Square(side)

    txtPerimeter.Text = plate.Perimeter
    txtArea.Text = plate.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:  305px;
}
</style>
<title>Geometry - Polygons: The Square</title>
</head>
<body>
<p id="main-title">Geometry - Polygons: The Square</p>
<form id="frmGeometry" runat="server">
<div id="whole">
 
<table>
  <tr>
    <td>Side:</td>
    <td><asp:TextBox id="txtSide" Width="75px" runat="server" /></td>
    </tr>
  <tr>
      <td>&nbsp;</td>
      <td><asp:Button id="btnCalculate" runat="server"
                                Text="Calculate" Width="85px"
                                OnClick="BtnCalculateClick" />
      </td>
  </tr>
    <tr>
      <td>Perimeter:</td>
      <td><asp:TextBox id="txtPerimeter" runat="server" /></td>
    </tr>
  <tr>
    <td>Area:</td>
    <td><asp:TextBox id="txtArea" runat="server" /></td>
  </tr>
</table>
</div>
</form>
</body>
</html>

You can also declare the variable and allocate its memory on the same line. Here is an example:

<script runat="server">
. . .

Sub btnCalculateClick(ByVal sender As Object, ByVal e As EventArgs)
    Dim side = 0.0
        
    If Not String.IsNullOrEmpty(txtSide.Text) Then
        side = CDbl(txtSide.Text)
    End If

    Dim plate As IPolygon = New Square(side)

    txtPerimeter.Text = plate.Perimeter
    txtArea.Text = plate.Area
End Sub
</script>

If you use any of these two techniques, you can access only the members of the interface. The non-interface members of the class would not be available. As a result, the following will produce an error:

<%@ Page Language="VB" %>

<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Interface IPolygon
    Property Side As Double
    ReadOnly Property Perimeter As Double
    ReadOnly Property Area As Double
End Interface

Public Class Square
    Implements IPolygon

    Protected Edge As Double

    Public Sub New(ByVal side As Double)
        Me.Edge = side
    End Sub

    Public Property Side As Double Implements IPolygon.Side
        Get
            Return Me.Edge
        End Get
        Set(ByVal value As Double)
            Me.Edge = value
        End Set
    End Property

    Public ReadOnly Property Diagonal As Double
        Get
            Return Me.Side * Math.Sqrt(2.00)
        End Get
    End Property

    ReadOnly Property Perimeter As Double Implements IPolygon.Perimeter
        Get
            Return Me.Side * 4.0
        End Get
    End Property

    ReadOnly Property Area As Double Implements IPolygon.Area
        Get
            Return Me.Side * Me.Side
        End Get
    End Property
End Class

Sub btnCalculateClick(ByVal sender As Object, ByVal e As EventArgs)
    Dim side = 0.0
        
    If Not String.IsNullOrEmpty(txtSide.Text) Then
        side = CDbl(txtSide.Text)
    End If

    Dim plate As IPolygon = New Square(side)

    txtPerimeter.Text = plate.Perimeter
    txtArea.Text = plate.Area
    ' Since the Diagonal is not a member of the interface, the variable 
    ' (declared from the interface) cannot access it
    txtDiagonal.Text = plate.Diagonal
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:  305px;
}
</style>
<title>Geometry - Polygons: The Square</title>
</head>
<body>
<p id="main-title">Geometry - Polygons: The Square</p>
<form id="frmGeometry" runat="server">
<div id="whole">
 
<table>
  <tr>
    <td>Side:</td>
    <td><asp:TextBox id="txtSide" Width="75px" runat="server" /></td>
    </tr>
  <tr>
      <td>&nbsp;</td>
      <td><asp:Button id="btnCalculate" runat="server"
                                Text="Calculate" Width="85px"
                                OnClick="BtnCalculateClick" />
      </td>
  </tr>
    <tr>
      <td>Diagonal:</td>
      <td><asp:TextBox id="txtDiagonal" runat="server" /></td>
    </tr>
    <tr>
      <td>Perimeter:</td>
      <td><asp:TextBox id="txtPerimeter" runat="server" /></td>
    </tr>
  <tr>
    <td>Area:</td>
    <td><asp:TextBox id="txtArea" runat="server" /></td>
  </tr>
</table>
</div>
</form>
</body>
</html>

Passing an Interface As Argument

If you are defining a procedure, a function, or a method that receives an argument and the argument is an object of a class that either inherits from another class or implements an interface, in some cases, you can pass either its parent class or the interface it implements. In the body of the procedure, you can access the members of the interface. Here is an example:

<%@ Page Language="VB" %>

<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Interface IPolygon
    Property Side As Double
    ReadOnly Property Perimeter As Double
    ReadOnly Property Area As Double
End Interface

Public Class Pentagon
    Implements IPolygon

    Protected Edge As Double

    Public Sub New(ByVal side As Double)
        Me.Edge = side
    End Sub

    Public Property Side As Double Implements IPolygon.Side
        Get
            Return Me.Edge
        End Get
        Set(ByVal value As Double)
            Me.Edge = value
        End Set
    End Property

    ReadOnly Property Perimeter As Double Implements IPolygon.Perimeter
        Get
            Return Me.Side * 5.0
        End Get
    End Property

    ReadOnly Property Area As Double Implements IPolygon.Area
        Get
            Return Me.Side * Me.Side * Math.Sqrt(5.00 * (5.00 + (2.00 * Math.Sqrt(5.00)))) / 4.00
        End Get
    End Property
End Class

Sub Present(ByVal figure As IPolygon)
    txtPerimeter.Text = figure.Perimeter
    txtArea.Text = figure.Area
End Sub

Sub btnCalculateClick(ByVal sender As Object, ByVal e As EventArgs)
    Dim side = 0.0
    Dim pol As IPolygon
    
    If Not String.IsNullOrEmpty(txtSide.Text) Then
        side = CDbl(txtSide.Text)
    End If

    pol = New Pentagon(side)
    Present(pol)
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:  305px;
}
</style>
<title>Geometry - Polygons: The Pentagon</title>
</head>
<body>
<p id="main-title">Geometry - Polygons: The Pentagon</p>
<form id="frmGeometry" runat="server">
<div id="whole">
 
<table>
  <tr>
    <td>Side:</td>
    <td><asp:TextBox id="txtSide" Width="75px" runat="server" /></td>
    </tr>
  <tr>
      <td>&nbsp;</td>
      <td><asp:Button id="btnCalculate" runat="server"
                                Text="Calculate" Width="85px"
                                OnClick="BtnCalculateClick" />
      </td>
  </tr>
    <tr>
      <td>Perimeter:</td>
      <td><asp:TextBox id="txtPerimeter" runat="server" /></td>
    </tr>
  <tr>
    <td>Area:</td>
    <td><asp:TextBox id="txtArea" runat="server" /></td>
  </tr>
</table>
</div>
</form>
</body>
</html>

Keep in mind that you can access only the members of the interface.

Returning an Interface

A function or a method can return an object based on an interface. When creating the function or method, specify its return type as the desired interface. Here is an example:

<script runat="server">
Interface IPolygon
    Property Side As Double
    ReadOnly Property Perimeter As Double
    ReadOnly Property Area As Double
End Interface

Function Create() As IPolygon
 
End Function
</script>

Remember that you cannot simply instantiate an interface and directly use it as you would an object of a class. As a result, you cannot directly return an object based on an interface. Instead, you can declare a variable of a class that implements the interface and return that variable. In the code section where you need to use the object, you can get the value returned by the function and use it. Here is an example:

<%@ Page Language="VB" %>

<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Interface IPolygon
    Property Side As Double
    ReadOnly Property Perimeter As Double
    ReadOnly Property Area As Double
End Interface

Public Class Pentagon
    Implements IPolygon

    Protected Edge As Double

    Public Sub New(ByVal side As Double)
        Me.Edge = side
    End Sub

    Public Property Side As Double Implements IPolygon.Side
        Get
            Return Me.Edge
        End Get
        Set(ByVal value As Double)
            Me.Edge = value
        End Set
    End Property

    Public ReadOnly Property Diagonal As Double
        Get
            Return Me.Side * ((1.00 * Math.Sqrt(5.00)) / 2.00)
        End Get
    End Property

    ReadOnly Property Perimeter As Double Implements IPolygon.Perimeter
        Get
            Return Me.Side * 5.0
        End Get
    End Property

    ReadOnly Property Area As Double Implements IPolygon.Area
        Get
            Return Me.Side * Me.Side * Math.Sqrt(5.00 * (5.00 + (2.00 * Math.Sqrt(5.00)))) / 4.00
        End Get
    End Property
End Class

Sub Present(ByVal figure As IPolygon)
    txtPerimeter.Text = figure.Perimeter
    txtArea.Text = figure.Area
End Sub

Function Create() As IPolygon
    Dim side As Double = 0.0
    Dim pol As IPolygon

    If Not String.IsNullOrEmpty(txtSide.Text) Then
        side = CDbl(txtSide.Text)
    End If

    pol = New Pentagon(side)
    Return pol
End Function

Sub btnCalculateClick(ByVal sender As Object, ByVal e As EventArgs)
    Dim shape As Pentagon
    
    shape = Create()
    Present(shape)
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:  305px;
}
</style>
<title>Geometry - Polygons: The Pentagon</title>
</head>
<body>
<p id="main-title">Geometry - Polygons: The Pentagon</p>
<form id="frmGeometry" runat="server">
<div id="whole">
 
<table>
  <tr>
    <td>Side:</td>
    <td><asp:TextBox id="txtSide" Width="75px" runat="server" /></td>
    </tr>
  <tr>
      <td>&nbsp;</td>
      <td><asp:Button id="btnCalculate" runat="server"
                                Text="Calculate" Width="85px"
                                OnClick="BtnCalculateClick" />
      </td>
  </tr>
    <tr>
      <td>Perimeter:</td>
      <td><asp:TextBox id="txtPerimeter" runat="server" /></td>
    </tr>
  <tr>
    <td>Area:</td>
    <td><asp:TextBox id="txtArea" runat="server" /></td>
  </tr>
</table>
</div>
</form>
</body>
</html>

In reality, the function must return an object based on either the interface itself or of a class that implements the interface.

Options on Creating, Implementing, and Using Interfaces

Inheriting an Interface

An interface can be derived from another interface but an interface cannot derive from a class. To create an interface based on another interface, use the Inherits keyword. A member of the parent interface cannot be defined in a derived interface.

The derived interface is supposed to add some behavior using methods and/or properties. In any class that needs the behaviors of the new interface, you must implement all members of the new interface and its parents. Here is an example:

open System
open System.Windows.Forms

type WorkingStatus =
| New
| Used
| NeedsRepair

type IProduct =
    abstract StockNumber : int    with get, set
    abstract ItemName    : string with get, set
    abstract UnitPrice   : float  with get, set

type ISalesTax =
    inherit IProduct
    abstract TaxRate : float with get, set
    abstract TaxAmount : float with get

type BoatPurchase(number, name, price, tRate) =
    let nbr  = ref number
    let nm   = ref name
    let cost = ref price
    let tr   = ref tRate
    
    interface ISalesTax with
        member this.StockNumber with get() = !nbr  and set(value) = nbr  := value
        member this.ItemName    with get() = !nm   and set(value) = nm   := value
        member this.UnitPrice   with get() = !cost and set(value) = cost := value
        member this.TaxRate     with get() = !tr   and set(value) = tr   := value
        member this.TaxAmount   with get() = !cost * !tr / 100.00

    member this.MarkedPrice with get() = !cost + (this :> ISalesTax).TaxAmount
                    
    member this.StockNumber with get() = (this :> ISalesTax).StockNumber
    member this.ItemName    with get() = (this :> ISalesTax).ItemName
    member this.UnitPrice   with get() = (this :> ISalesTax).UnitPrice

let rndNumber = new Random()
let strStockNumber = string (rndNumber.Next(100, 999)) + "-" + string (rndNumber.Next(100, 999))

let item = BoatPurchase((rndNumber.Next(10000, 90000)), "Self-Propelled Gas Mower with Auto Choke", 399.95, 7.75)
let salesTax = (item :> ISalesTax).TaxAmount

// Form: Water Runner
let waterRunner = new Form(Width = 388, Height = 238, Text = "Water Runner")

// Label: Stock Number
waterRunner.Controls.Add(new Label(Left = 17, Top = 22, Width = 75, Text = "Stock #:"))

// Text Box: Stock Number
let txtStockNumber = new TextBox(Left = 113, Top = 19, Width = 78)
waterRunner.Controls.Add txtStockNumber

// Label: Status
waterRunner.Controls.Add(new Label(Left = 205, Top = 21, Width = 54, Text = "Status:"))

// Combo Box: Status
let cbxStatus = new ComboBox(Left = 275, Top = 19,  Width = 90, Text = "New")
cbxStatus.Items.AddRange([| "New"; "Used"; "Needs Repair" |])
waterRunner.Controls.Add cbxStatus

// Label: Boat Model
waterRunner.Controls.Add(new Label(Left = 17, Top = 51, Width = 75, Text = "Boat Model:"))

// Text Box: Model
let txtBoatModel = new TextBox(Left = 113, Top =  48, Width = 250)
waterRunner.Controls.Add txtBoatModel

// Label: Seating Capacity
waterRunner.Controls.Add(new Label(Left = 17, Top = 79, Width = 95, Text = "Seating Capacity:"))

// Text Box: Seating Capacity
let txtSeatingCapacity = new TextBox(Left = 113, Top = 77, Width = 75, Text = "1")
waterRunner.Controls.Add txtSeatingCapacity

// Label: Retail Price
waterRunner.Controls.Add(new Label(Left = 205, Top = 80, Width = 68, Text = "Retail Price:"))

// Text Box: Retail Price
let txtRetailPrice = new TextBox(Left = 275, Top = 77, Width = 90, Text = "0.00")
waterRunner.Controls.Add txtRetailPrice

// Label: Tax Rate
waterRunner.Controls.Add(new Label(Left = 18, Top = 106, Width = 78, Text = "Tax Rate:"))

// Text Box: Tax Rate
let txtTaxRate = new TextBox(Left = 114, Top =  106, Width = 60, Text = "7.75")
waterRunner.Controls.Add txtTaxRate

// Label: %
waterRunner.Controls.Add(new Label(Left = 175, Top = 109, Width = 14, Text = "%"))

// Label: Tax Amount
waterRunner.Controls.Add(new Label(Left = 17, Top = 138, Width = 85, Text = "Tax Amount:"))

// Text Box: Tax Amount
let txtTaxAmount = new TextBox(Left = 113, Top = 135, Width = 75, Text = "0.00")
waterRunner.Controls.Add txtTaxAmount

// Label: Sale Price
waterRunner.Controls.Add(new Label(Left = 205, Top = 138, Width = 62, Text = "Sale Price:"))

// Text Box: Sale Price
let txtSalePrice = new TextBox(Left = 275, Top = 135, Width = 90, Text = "0.00")
waterRunner.Controls.Add txtSalePrice

// Button: Calculate
let btnCalculate = new Button(Left = 275, Top = 106, Width = 90, Text = "Calculate")
let btnCalculateClick e =
    let boat = new BoatPurchase(int txtStockNumber.Text, txtBoatModel.Text, float txtRetailPrice.Text, float txtTaxRate.Text)

    let strTax = sprintf "%0.02f" (boat :> ISalesTax).TaxAmount
    let strSalePrice = sprintf "%0.02f" boat.MarkedPrice

    txtTaxAmount.Text <- strTax
    txtSalePrice.Text <- strSalePrice
btnCalculate.Click.Add btnCalculateClick
waterRunner.Controls.Add btnCalculate

// Button: Close
let btnClose = new Button(Left = 275, Top = 174, Width = 90, Text = "Close")
let btnCloseClick e = waterRunner.Close()
btnClose.Click.Add btnCloseClick
waterRunner.Controls.Add btnClose

do Application.Run waterRunner

In the same way, an interface can inherit from as many interfaces as necessary.

Implementing Many Interfaces

F# doesn't support multiple inheritance, which is the ability to create a class that is directly based on many classes. As an alternative, you can create a class that implements more than one interface.

The formula to implement many interfaces is:

type Class-Name[(Parametere(s))] =
    Member(s)
    interface InterfaceName 1 with
  	Interface-Member(s) 1
    interface InterfaceName 2 with
  	Interface-Member(s) 2
    . . .
    interface InterfaceName n with
  	Interface-Member(s) n

In the body of the class, each interface has its implementation section. The individual implementations follow the techniques we have used so far. To access the member of an interface from the object created using the class, you can declare a variable that is up-cast from the interface. This can be done as follows:

open System
open System.Windows.Forms

type IProduct =
    abstract ItemNumber : int    with get, set
    abstract ItemName   : string with get, set
    abstract UnitPrice  : float  with get, set

type IDiscount =
    abstract DiscountRate : float with get, set
    abstract DiscountAmount : float with get

type StoreItem(number, make, category, subcat, name, size, price, discrate) =
    let nbr = ref number
    let mutable mk = make
    let mutable cat = category
    let mutable sub = subcat
    let nm = ref name
    let mutable sz = size
    let prc = ref price
    let dr = ref discrate
    
    interface IProduct with
        member this.ItemNumber with get() = !nbr and set(value) = nbr := value
        member this.ItemName   with get() = !nm  and set(value) = nm  := value
        member this.UnitPrice  with get() = !prc and set(value) = prc := value
    
    interface IDiscount with
        member this.DiscountRate   with get() = !dr and set(value) = dr := value
        member this.DiscountAmount with get() = !prc * !dr / 100.00

    member this.Manufacturer   with get() = mk   and set(value) = mk   <- value
    member this.Category       with get() = cat  and set(value) = cat  <- value
    member this.SubCategory    with get() = sub  and set(value) = sub  <- value
    member this.ItemSize       with get() = sz   and set(value) = sz   <- value
    
    member this.MarkedPrice    with get() = this.UnitPrice - (this :> IDiscount).DiscountAmount
    new() = StoreItem(0, "", "", "", "", "", 0.00, 0.00)
    new(number, make, category, subcategory, name, size, price) = StoreItem(number, make, category, subcategory, name, size, price, 0.00)

    override this.GetHashCode() = this.GetHashCode()
    
    override this.Equals(obj) =
            match obj with
            | :? StoreItem as si -> this.ItemNumber = si.ItemNumber
            | _ -> false

    override this.ToString() =
        "Item #: " + string this.ItemNumber + ", " + this.Manufacturer + ", " + this.Category + " " + this.SubCategory + ", Named " + this.ItemName + "(" + this.ItemSize + "), Price: " + string this.UnitPrice

    interface IComparable with
        member this.CompareTo(obj : Object) : int =
            match obj with
            | :? StoreItem as si -> compare this.ItemName si.ItemName
            | _ -> 0
                                
    member this.ItemNumber      with get() = (this :> IProduct).ItemNumber
    member this.ItemName        with get() = (this :> IProduct).ItemName
    member this.UnitPrice       with get() = (this :> IProduct).UnitPrice
    member this.DiscountRate    with get() = (this :> IDiscount).DiscountRate
    member this.DiscountAmount  with get() = (this :> IDiscount).DiscountAmount 

let rndNumber = new Random()

let si = new StoreItem(rndNumber.Next(100001, 999999), "Guess", "Women", "Dresses", "Zip Front Fit and Flare Dressr", "4", 135.75, float 25)

// Form: Department Store
let departmentStore = new Form(Width = 390, Height = 238, Text = "Department Store")

// Label: Item Number
departmentStore.Controls.Add(new Label(Left = 22, Top = 18, Width = 74, Text = "Item #:"))

// Text Box: Item Number
let txtItemNumber = new TextBox(Left = 101, Top = 15, Width = 64)
txtItemNumber.Text <- string si.ItemNumber
departmentStore.Controls.Add txtItemNumber

// Label: Manufacturer
departmentStore.Controls.Add(new Label(Left = 22, Top = 44, Width = 74, Text = "Manufacturer:"))

// Text Box: Manufacturer
let txtManufacturer = new TextBox(Left = 101, Top = 41, Width = 262)
txtManufacturer.Text  <- si.Manufacturer
departmentStore.Controls.Add txtManufacturer

// Label: Category
departmentStore.Controls.Add(new Label(Left = 22, Top = 70, Width = 52, Text = "Category:"))

// Text Box: Category
let txtCategory = new TextBox(Left = 101, Top = 67, Width = 87)
txtCategory.Text  <- si.Category
departmentStore.Controls.Add txtCategory

// Label: Sub-Category
let lblSubCategory = new Label(Left = 194, Top = 70, Width = 78, Text = "Sub-Category:")

departmentStore.Controls.Add lblSubCategory

// Text Box: Sub-Category
let txtSubCategory = new TextBox(Left = 274, Top =  67, Width =  90)
txtSubCategory.Text  <- si.SubCategory
departmentStore.Controls.Add txtSubCategory

// Label: Item Name
departmentStore.Controls.Add(new Label(Left = 22, Top = 96, Width = 68, Text = "Item Name:"))

// Text Box: Item Name
let txtItemName = new TextBox(Left = 101, Top =  93, Width = 262)
txtItemName.Text  <- si.ItemName
departmentStore.Controls.Add txtItemName

// Label: Item Size
departmentStore.Controls.Add(new Label(Left = 22, Top = 122, Width = 64, Text = "Item Size:"))

// Text Box: Item Size
let txtItemSize = new TextBox(Left = 101, Top = 119, Width = 87)
txtItemSize.Text <- si.ItemSize
departmentStore.Controls.Add txtItemSize

// Label: Unit Price
departmentStore.Controls.Add(new Label(Left = 194, Top = 122, Width = 75, Text = "Unit Price:"))

// Text Box: Unit Price
let txtUnitPrice = new TextBox(Left = 288, Top = 119, Width = 75)
txtUnitPrice.Text  <- sprintf "%g" si.UnitPrice
departmentStore.Controls.Add txtUnitPrice

// Label: Discount Rate
let lblDiscountRate = new Label(Left = 22, Top = 148, Width = 78, Text = "Discount Rate:")
departmentStore.Controls.Add lblDiscountRate

// Text Box: Discount Rate
let txtDiscountRate = new TextBox(Left = 101, Top = 145, Width =  87)
txtDiscountRate.Text  <- (sprintf "%g%c" si.DiscountRate '%')
departmentStore.Controls.Add txtDiscountRate

// Label: Discount Amount
let lblDiscountAmount = new Label(Left = 194, Top = 148, Width = 94, Text = "Discount Amount:")
departmentStore.Controls.Add lblDiscountAmount

// Text Box: Discount Amount
let txtDiscountAmount = new TextBox(Left = 288, Top = 145, Width = 75)
txtDiscountAmount.Text <- sprintf "%0.02f" si.DiscountAmount
departmentStore.Controls.Add txtDiscountAmount

// Label: Marked Price
departmentStore.Controls.Add(new Label(Left = 22, Top = 174, Width = 77, Text = "Marked Price:"))

// Text Box: MarkedPrice
let txtMarkedPrice = new TextBox(Left = 101, Top = 171, Width = 87)
txtMarkedPrice.Text <- sprintf "%0.02f" si.MarkedPrice
departmentStore.Controls.Add txtMarkedPrice

// Button: Close
let btnClose = new Button(Left = 288, Top = 174, Text = "Close")
let btnCloseClick e = departmentStore.Close()
btnClose.Click.Add btnCloseClick
departmentStore.Controls.Add btnClose

do Application.Run departmentStore

Multiple Derivations

As we know already, you can create a class that is based on another class, and you can create a class that implements an interface. You are not allowed to create a class that is directly based on more than one class. Instead you can either use transitive inheritance, in which case one class is based on another class that itself is based on another class. Or you can create a class that implements many interfaces. That, you can create a class that implements more than one interface. In the body of the class, create a section for each interface and implement all its members. Here is an example:

open System
type IProduct =
    abstract ItemNumber : string with get, set
    abstract ItemName   : string with get, set
    abstract UnitPrice  : float  with get, set
type ISalesTax =
    abstract TaxRate : float with get, set
    abstract TaxAmount : float with get

type VehiclePurchase(number, name, price, tRate) =
    let nbr  = ref number
    let nm   = ref name
    let cost = ref price
    let tr   = ref tRate
    
    interface IProduct with
        member this.ItemNumber with get() = !nbr  and set(value) = nbr  := value
        member this.ItemName   with get() = !nm   and set(value) = nm   := value
        member this.UnitPrice  with get() = !cost and set(value) = cost := value
    
    interface ISalesTax with
        member this.TaxRate    with get() = !tr   and set(value) = tr   := value
        member this.TaxAmount  with get() = !cost * !tr / 100.00

    member this.MarkedPrice with get() = !cost + (this :> ISalesTax).TaxAmount
                    
    member this.ItemNumber   with get() = (this :> IProduct).ItemNumber
    member this.ItemName     with get() = (this :> IProduct).ItemName
    member this.UnitPrice    with get() = (this :> IProduct).UnitPrice
    //member this.TaxRate    with get() = (this :> ISalesTax).TaxRate
    //member this.TaxAmount  with get() = (this :> ISalesTax).TaxAmount

let rndNumber = new Random()
let strItemNumber = string (rndNumber.Next(100, 999)) + "-" + string (rndNumber.Next(100, 999)) + "-" + string (rndNumber.Next(100, 999))

let registrationFee = 128.00
let downPayment = 3000.00
let item = VehiclePurchase(strItemNumber, "Toyota Camry (2010)", 18750.00 - downPayment + registrationFee, 7.75)
let salesTax = (item :> ISalesTax).TaxAmount
-------------------------------------------------------------------------

An Interface Derived

Like a regular class, an interface can be derived from another interface but an interface cannot derive from a class. To create an interface based on another, use the Inherits keyword. As mentioned for the interfaces, you can use the parent interface to list the members that the deriving classes would implement. Still remember that since an interface cannot implement a member, the member of the parent interface cannot be defined in a derived interface. This implement would wait for the actual class(es) that would be based on the child (or even the parent) interface. Here is an example:

File: RegularTriangle.vb
Public Interface IGeometricShape
    ReadOnly Property Type() As String
End Interface

Public Interface ITriangle
    Inherits IGeometricShape

    ReadOnly Property Name() As String
    Property Base() As Double
    Property Height() As Double

    Function CalculatePerimeter() As Double
    Function CalculateArea() As Double
End Interface

After deriving a class from an interface, when defining the class, you must implement the member of the immediate interface and those of the ancestor interface(s). Here is an example:

File: RegularTriangle.vb
Public Interface IGeometricShape
    ReadOnly Property Type() As String
End Interface

Public Interface ITriangle
    Inherits IGeometricShape

    ReadOnly Property Name() As String
    Property Base() As Double
    Property Height() As Double

    Function CalculatePerimeter() As Double
    Function CalculateArea() As Double
End Interface

Public Class RegularTriangle
    Implements ITriangle

    Public bas As Double
    Public hgt As Double
    Public sd1 As Double
    Public sd2 As Double

    Public ReadOnly Property Type() As String Implements ITriangle.type
        Get
            Return "Triangle"
        End Get
    End Property

    ' Default constructor: the user will specify the dimensions
    Public Sub New()
        bas = 0
        hgt = 0
        sd1 = 0
        sd2 = 0
    End Sub

    ' A triangle based on known base and height
    Public Sub New(ByVal b As Double, ByVal h As Double)
        bas = b
        hgt = h
    End Sub

    ' A triangle based on the measurements of the sides
    Public Sub New(ByVal b As Double, ByVal side1 As Double, ByVal side2 As Double)
        bas = b
        sd1 = side1
        sd2 = side2
    End Sub

    ' A triangle whose all sides and the height are known
    Public Sub New(ByVal b As Double, ByVal h As Double, _
                   ByVal side1 As Double, ByVal side2 As Double)
        bas = b
        hgt = h
        sd1 = side1
        sd2 = side2
    End Sub

    Public Property Base() As Double Implements ITriangle.Base
        Get
            Return bas
        End Get
        Set(ByVal Value As Double)
            If bas < 0 Then
                bas = 0
            Else
                bas = Value
            End If
        End Set
    End Property

    Public Function CalculateArea() As Double Implements ITriangle.CalculateArea
        Return bas * hgt / 2
    End Function

    Public Function CalculatePerimeter() As Double Implements _
   ITriangle.CalculatePerimeter
        Return bas + sd1 + sd2
    End Function

    Public Property Height() As Double Implements ITriangle.Height
        Get
            Return hgt
        End Get
        Set(ByVal Value As Double)
            If hgt < 0 Then
                hgt = 0
            Else
                hgt = Value
            End If
        End Set
    End Property

    Public ReadOnly Property Name() As String Implements ITriangle.Name
        Get
            Return "Regular"
        End Get
    End Property
End Class

Here is an example of testing the class:

File: Exercise.vb
Module Exercise

    Public Function Main() As Integer
        Dim reg As RegularTriangle = New RegularTriangle(35.28, 26.44)

        Console.WriteLine("Shape Type:    {0}", reg.Type)
        Console.WriteLine("Triangle Type: {0}", reg.Name)
        Console.WriteLine("=-= Characteristics =-=")
        Console.WriteLine("Base:   {0}", reg.Base)
        Console.WriteLine("Height: {0}", reg.Height)
        Console.WriteLine("Area:   {0}", reg.CalculateArea)

        Return 0
    End Function

End Module

This would produce:

Shape Type:    Triangle
Triangle Type: Regular
=-= Characteristics =-=
Base:   35.28
Height: 26.44
Area:   466.4016

Multiple Inheritance

Multiple inheritance consists of creating a class that is based on more than one parent. In the Microsoft Visual Basic language (in fact in the .NET Framework), you cannot derive a class from more than one class. This functionality is available only with interfaces.

To create a class based on more than one interface, after the Implements keyword, enter the name of each interface and separate them with commas. Here is an example:

Public Interface IGeometricShape
    ReadOnly Property Type() As String
End Interface

Public Interface ICalculation

End Interface

Public Interface ITriangle
    Inherits IGeometricShape, ICalculation

End Interface

The same rules apply for multiple inheritance: you must implements all members of each parent interface.

Besides deriving from an interface, you can also create a class that is based on a class and one or more interfaces. To do this, under the line that specifies the name of the class, use the Inherits keyword to specify the name of the parent, press Enter, and use the Implements keyword to specify the name of the class that serves as the parent interface. Here is an example:

Introduction



Therefore, when implementing the ICloneable interface, in your class, you can simply call the MemberwiseClone() method.

Comparing Two Objects

Comparing two objects consists of finding out which one comes before. The comparison is simple if you are dealing with values of primitive types. For example, it is easy to know that 2 is lower than 5, but it is not obvious to compare two objects created from a composite type, such as two students, two cars, or two food items.

To assist you with comparing two objects, the .NET Framework provides various comparable interfaces. One of these interfaces is named IComparable. The IComparable interface is a member of the System namespace. Obviously you must define what would be compared and how the comparison would be carried. For example, to compare two Student objects of the above class, you can ask the compiler to base the comparison on the student number. Here is an example:

open System
open System.Windows.Forms

type StoreItem(number, make, category, subcategory, name, size, price, discrate) =
    let mutable nbr = number
    let mutable mk = make
    let mutable cat = category
    let mutable sub = subcategory
    let mutable nm = name
    let mutable sz = size
    let mutable prc = price
    let mutable rate = discrate

    member this.ItemNumber     with get() = nbr  and set(value) = nbr  <- value
    member this.Manufacturer   with get() = mk   and set(value) = mk   <- value
    member this.Category       with get() = cat  and set(value) = cat  <- value
    member this.SubCategory    with get() = sub  and set(value) = sub  <- value
    member this.ItemName       with get() = nm   and set(value) = nm   <- value
    member this.ItemSize       with get() = sz   and set(value) = sz   <- value
    member this.UnitPrice      with get() = prc  and set(value) = prc  <- value
    member this.DiscountRate   with get() = rate and set(value) = rate <- value
    member this.DiscountAmount with get() = this.UnitPrice * this.DiscountRate / 100.00
    member this.MarkedPrice    with get() = this.UnitPrice - this.DiscountAmount
    new() = StoreItem("", "", "", "", "", "", 0.00, 0.00)
    new(number, make, category, subcategory, name, size, price) = StoreItem(number, make, category, subcategory, name, size, price, 0.00)

    override this.Equals(obj) =
            match obj with
            | :? StoreItem as si -> this.ItemNumber = si.ItemNumber
            | _ -> false

    override this.ToString() =
        "Item #: " + this.ItemNumber + ", " + this.Manufacturer + ", " + this.Category + " " + this.SubCategory + ", Named " + this.ItemName + "(" + this.ItemSize + "), Price: " + string this.UnitPrice

    interface IComparable with
        member this.CompareTo(obj : Object) : int =
            match obj with
            | :? StoreItem as si -> compare this.ItemName si.ItemName
            | _ -> 0

let si1 = new StoreItem("279403", "Reef", "Men", "Sandals", "Men's Phantom Ultimate Flip Flop", "10", 45.50, float 0)
let si2 = new StoreItem("927497", "Guess", "Women", "Dresses", "Zip Front Fit and Flare Dressr", "4", 155.75, float 25)
let si3 = new StoreItem("293041", "Anne Klein", "Women", "Skirts", "A-Line Skirt with Lining", "4", 82.50, float 50)
let si4 = new StoreItem("537946", "Guess", "Women", "Dresses", "Zip Front Fit and Flare Dressr", "4", 155.75, float 25)

let comparison1 = sprintf "%i" ((si1 :> IComparable).CompareTo(si2))
let comparison2 = sprintf "%i" ((si1 :> IComparable).CompareTo(si3))
let comparison3 = sprintf "%i" ((si2 :> IComparable).CompareTo(si4))

// Form: Department Store
let departmentStore = new Form()
departmentStore.Width  <- 520
departmentStore.Height <- 225
departmentStore.Text   <- "Department Store"

// Label: Item 1
let lblItem1 = new Label()
lblItem1.Left   <- 12
lblItem1.Top    <- 18
lblItem1.Width  <- 500
lblItem1.Text   <- si1.ToString()
departmentStore.Controls.Add lblItem1

// Label: Item 3
let lblItem2 = new Label()
lblItem2.Left   <- 12
lblItem2.Top    <- 42
lblItem2.Width  <- 500
lblItem2.Text   <- si2.ToString()
departmentStore.Controls.Add lblItem2

// Label: Item 3
let lblItem3 = new Label()
lblItem3.Left   <- 12
lblItem3.Top    <- 64
lblItem3.Width  <- 500
lblItem3.Text   <- si3.ToString()
departmentStore.Controls.Add lblItem3

// Label: Item 4
let lblItem4 = new Label()
lblItem4.Left   <- 12
lblItem4.Top    <- 88
lblItem4.Width  <- 500
lblItem4.Text   <- si4.ToString()
departmentStore.Controls.Add lblItem4

// Label: Comparison 1
let lblComparison1 = new Label()
lblComparison1.Left   <- 12
lblComparison1.Top    <- 118
lblComparison1.Width  <- 500
lblComparison1.Text   <- "Item 927497 compared to 279403 produces: " + comparison1.ToString()
departmentStore.Controls.Add lblComparison1

// Label: Comparison 2
let lblComparison2 = new Label()
lblComparison2.Left  <-  12
lblComparison2.Top   <- 142
lblComparison2.Width <- 500
lblComparison2.Text  <- "Item 927497 compared to 537946 produces: " + comparison2.ToString()
departmentStore.Controls.Add lblComparison2

// Label: Comparison 3
let lblComparison3 = new Label()
lblComparison3.Left   <- 12
lblComparison3.Top    <- 168
lblComparison3.Width  <- 500
lblComparison3.Text   <- "Item 279403 compared to 293041 produces: " + comparison3.ToString()
departmentStore.Controls.Add lblComparison3

do Application.Run departmentStore

This would produce:

Comparing Two Objects

As mentioned for disposing of an object, there are two main ways you can use the IFormatProvider. You can create a class that implements it. The IFormatProvider is equipped with only one method: GetFormatIn most cases, you will use classes that already implement the IFormatProvider interface. Those classes are equipped with an overridden version of the ToString() method that takes IFormatProvider as argument. Its signature is:This ToString() method whose signature is:

Finally
End Try
Try
Finally
End Try

Instead of simply adding a new node at the end of child nodes, you can specify any other position you want. For example, you may want the new node to precede an existing child node. To support this operation, the XmlNode class provides the InsertBefore() method. Its syntax is:

Public Overridable Function InsertBefore(ByVal newChild As XmlNode,
					 ByVal refChild As XmlNode) As XmlNode

The first argument of this method is the new node that will be added. The second argument is the sibling that will succeed the new node. Consider the following version of our Videos.xml file:

<?xml version="1.0" encoding="utf-8"?>
<videos>
    <video>
      	<title>The Distinguished Gentleman</title>
      	<director>Jonathan Lynn</director>
      	<length>112 Minutes</length>
      	<format>DVD</format>
      	<rating>R</rating>
      	<category>Comedy</category>
    </video>
    <video>
	<title>Fatal Attraction</title>
	<director>Adrian Lyne</director>
	<length>119 Minutes</length>
	<format>DVD</format>
	<rating>R</rating>
    </video>
</videos>

Imagine you want to create a new category element below the director element whose name is Adrian Lyne. You can first get a list of videos. Inside of each video, check the nodes and find out whether the video has a director node whose text is Adrian Lyne. Once you find that node, you can add the new element after it. Here is an example:

open System
open System.IO
open System.Xml
open System.Drawing
open System.Windows.Forms

let exercise = new Form(MaximizeBox = false, Text = "Video Collection",
                        ClientSize = new System.Drawing.Size(225, 120),
                        StartPosition = FormStartPosition.CenterScreen)

let btnDocument = new Button(Text = "Document", Location = new Point(12, 12), Width = 100)
exercise.Controls.Add btnDocument

let btnDocumentClick _ =
    let strFileName = "..\..\Videos.xml"
    let xdVideos : XmlDocument = new XmlDocument()

    if File.Exists strFileName then
        use fsVideo = new FileStream(strFileName, FileMode.Open, FileAccess.Read)
        xdVideos.Load strFileName
        fsVideo.Close()

        // Create a list of nodes whose name is Title
        let xnlVideos : XmlNodeList = xdVideos.GetElementsByTagName "video"
    
        use fsVideo = new FileStream(strFileName, FileMode.Create, FileAccess.Write)

        // Now you can check each node of the list
        for xnTitle in xnlVideos do
            // Within a video, create a list of its children
            let xnlChildren : XmlNodeList = xnTitle.ChildNodes

            // Visit each child node
            for xnChild in xnlChildren do
                // If the child node is (a xnChildector and its name is) Adrian Lyne
                if xnChild.InnerText = "Adrian Lyne" then
                    // Create an element named Category
                    let xeVideo : XmlElement = xdVideos.CreateElement "category"
                    // Specify the text of the new element
                    xeVideo.InnerText <- "Drama"

                    // Insert the new node below the Adrian Lyne node xnChildector
                    xnTitle.InsertAfter(xeVideo, xnChild)

This would produce:



In the same way, you can insert a new node after a child of a child (or of a child of a child of a child) of any node.

XmlNode.InsertAfter():



Here are examples:

.ToString("e")

Here is an example of executing the program:

Formatting a String

IEnumerator:

Current) MoveNext and Reset). Normally, you will not need to use that property or to call those methods. As we will see in this lesson, the operations are performed behind the scenes for you. You may be concerned with the IEnumerator.

The IEnumerable interface GetEnumerator. Its signature is:

.InIList. It implements both the ICollection and the IEnumerable interfaces:

The IList ListBox is based on a custom class named ObjectCollection. It implements the IList, the ICollection, and the IEnumerable interface:

Here is an example of using the webpage:

Creating a Simple Action

This would produce:

Functions Delegates

lbxManufacturers.Items.Add "Jaguar"

Here is an example of using the webpage:

Introduction to Lists and Collections

Here is an example of using the webpage:

Introduction to Lists and Collections

lbxManufacturers.Items.Add "Lincoln"
Items.Insert(2, "Ford")

Here is an example of using the webpage:

Introduction to Lists and Collections

(
)
.Invoke( milesDriven, rate)

Here is an example of using the webpage:

Introduction to Lists and Collections

Here is an example of using the webpage:

Introduction to Lists and Collections

Items.Contains("Toyota")

Here is an example of using the webpage:

Introduction to Lists and Collections

Here is an example:

Here is an example of testing the program:

Characteristics of Function Delegates Characteristics of Function Delegates

Now consider the following file:

<?xml version="1.0" encoding="utf-8"?>
<videos>
  <video>
    <title>The Distinguished Gentleman</title>
    <director>Jonathan Lynn</director>
    <length>112 Minutes</length>
    <format>DVD</format>
    <rating>R</rating>
  </video>
  <video>
    <title>Her Alibi</title>
    <director>Bruce Beresford</director>
    <length>94 Minutes</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
</videos>

The root, videos, has a child named video. The video node has many child nodes. By now, we know how to add a child to the root. We also saw how to add a grand child with value to the root. To add many (grand) children to a node, first build the node, add it to the root, then continuously add the necessary nodes, one at a time, including its name and its optional value. This would be done as follows:

open System
open System.IO
open System.Xml
open System.Drawing
open System.Windows.Forms

let exercise = new Form(MaximizeBox = false, Text = "Video Collection",
                        ClientSize = new System.Drawing.Size(225, 120),
                        StartPosition = FormStartPosition.CenterScreen)

let btnDocument = new Button(Text = "Start XML File", Location = new Point(12, 12), Width = 100)
exercise.Controls.Add btnDocument

let btnDocumentClick _ =
    let strFileName = "..\..\Videos.xml"
    let xdVideoCollection : XmlDocument = new XmlDocument()

    if File.Exists(strFileName) = false then
        Using fsVideo As New FileStream(strFileName, FileMode.Create, FileAccess.Write)
        xdVideoCollection.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" &
                                  "<videos></videos>")
        xdVideoCollection.Save(fsVideo)
        fsVideo.Close()

    Using fsVideo As New FileStream(strFileName, FileMode.Open, FileAccess.Read)
    xdVideoCollection.Load fsVideo
    fsVideo.Close()

    Using fsVideo As New FileStream(strFileName, FileMode.Create, FileAccess.Write)
    let xeRoot : XmlElement = xdVideoCollection.DocumentElement

    let mutable xeVideo : XmlElement = xdVideoCollection.CreateElement "video"
    xeRoot.AppendChild xeVideo |> ignore
    xeVideo <- xdVideoCollection.CreateElement "title"
    let txtvideo : XmlText = xdVideoCollection.CreateTextNode("The Day After Tomorrow")
    xeRoot.LastChild.AppendChild xeVideo |> ignore
    xeRoot.LastChild.LastChild.AppendChild txtvideo |> ignore
    
    xeVideo <- xdVideoCollection.CreateElement "director"
    let txtvideo : XmlText = xdVideoCollection.CreateTextNode("Roland Emmerich")
    xeRoot.LastChild.AppendChild xeVideo |> ignore
    xeRoot.LastChild.LastChild.AppendChild txtvideo |> ignore
    
    xeVideo <- xdVideoCollection.CreateElement "length"
    let txtvideo : XmlText = xdVideoCollection.CreateTextNode("124 Minutes")
    xeRoot.LastChild.AppendChild xeVideo |> ignore
    xeRoot.LastChild.LastChild.AppendChild txtvideo |> ignore
    
    xeVideo <- xdVideoCollection.CreateElement "format"
    let txtvideo : XmlText = xdVideoCollection.CreateTextNode("DVD")
    xeRoot.LastChild.AppendChild xeVideo |> ignore
    xeRoot.LastChild.LastChild.AppendChild txtvideo |> ignore
    
    xeVideo <- xdVideoCollection.CreateElement "rating"
    let txtvideo : XmlText = xdVideoCollection.CreateTextNode("PG-13")
    xeRoot.LastChild.AppendChild xeVideo |> ignore
    xeRoot.LastChild.LastChild.AppendChild txtvideo |> ignore

 This would produce:

<?xml version="1.0" encoding="utf-8"?>
<videos>
  <video>
    <title>The Distinguished Gentleman</title>
    <director>Jonathan Lynn</director>
    <length>112 Minutes</length>
    <format>DVD</format>
    <rating>R</rating>
  </video>
  <video>
    <title>Her Alibi</title>
    <director>Bruce Beresford</director>
    <length>94 Minutes</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
  <video>
    <title>The Day After Tomorrow</title>
    <director>Roland Emmerich</director>
    <length>124 Minutes</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
</videos>



XmlDocument:


Here is an example that uses a file stream:

This would produce:



let
let
xeParent












let xnlActors : XmlNodeList = xnVideo.ChildNodes
for xnActor in xnlActors do
if xnActor.Name = "actors" then
                        // Create a new element named Actor
                        // Specify its name as Actor
                        let mutable xeVideo : XmlElement = xdVideos.CreateElement "actor"
                        // Create the text of the new element
                        let mutable txtActor : XmlText = xdVideos.CreateTextNode "Tom Selleck"
                        // Add the new Actor element to the Actors node
                        xnVideo.LastChild.AppendChild xeVideo |> ignore
                        // Specify the text of the new node
                         |> ignore
                        
                        xnVideo.LastChild.LastChild.AppendChild txtActor

                        
                        xnVideo.LastChild.LastChild.AppendChild txtActor