Classes, Namespaces, Properties, and Forms

 <  Day Day Up  >  

Many FoxPro developers began with version 1, which didn't have object orientation. We built forms that did what we wanted. If we needed a similar form, we cloned and modified the code. There was a template capability that allowed us to migrate features to the template and then stamp out similar forms like a cookie- cutter . But subsequent design changes could be painful.

When Visual FoxPro came out, for the first time we had the ability to write generic form class code and inherit forms from it. My own approach was to build a basic form and then slowly move code out of it into an underlying class, changing form references to a specific table name to the contents of a property, so if I changed

 

 SELECT EMPLOYEES 

to

 

 SELECT ( THISFORM.MainTable ) 

I could base a form on this "form template," assign a value to the MainTable property, and the form would run as expected. Gradually, most if not all of the code in the original form migrated to the class. I ended up with a form that did what I needed if I set a dozen or so properties; if I needed a similar form, I just used

 

 Create form xxx as MyForm FROM PinterLIB 

And set the same dozen properties, and the form was up and running in minutes. I was in heaven! My customers got more software for less money, and I could win every single bid I made.

Visual Basic .NET is similarly object-oriented.

However, classes don't work exactly the same way. For one thing, FoxPro form classes are usually stored in a table with the extension .vcx (and an associated memo file with the same name and a .vct extension). Visual Basic .NET forms are source code files that don't look any different from program files. They have the extension .vb .

However, the general idea is the same: Classes have properties and methods. You instantiate an object based on the class, assign values to its public properties, and call its public methods . It uses its private properties as variables , and calls private methods to do its work. In this regard, FoxPro and Visual Basic .NET are identical.

However, the devil is in the details. And there are lots of details that differ . For one thing, FoxPro classes are stored either as VCX files or PRG files. If they're stored as VCX files, you use the Class Designer to add properties and methods, which can be either Public , Private , or Protected . If they're defined in a PRG, the file starts with this line of code

 

 DEFINE CLASS Foobar AS CUSTOM (OLEPUBLIC) 

and ends with

 

 ENDDEFINE 

The OLEPUBLIC keyword is required if you want to compile to a DLL, which is required for Web Services applications, and is generally not used by FoxPro developers unless they use COM+.

Properties are created simply by assigning them values, one per line, after the DEFINE CLASS statement and before the first FUNCTION or PROCEDURE statement. A single PRG can have one or more class definitions in it. They're instantiated using either

 

 SET CLASSLIB TO VCXNAME ADDITIVE or SET PROCLIB TO CLSLIB.PRG ADDITIVE 

followed by

 

 oName  = CREATEOBJECT ( "ClassName" ) oName2 = CREATEOBJECT ( "OtherClass" ) 

or you can skip the SET CLASSLIB and SET PROCLIB statements and use a shorter approach:

 

 oName  = NEWOBJECT ( "ClassName", "VCXNAME.VCX" ) oName2 = NEWOBJECT ( "OtherClass", "CLSLIB.PRG" ) 

If you have parameters in a class's Init method, you can add the parameters at the end of the CREATEOBJECT() or NEWOBJECT() function call and pass them directly to the Init constructor. Inside the class, THIS refers to a property or method of the class itself. That's about the size of creating and using classes in FoxPro.

In Visual Basic .NET, classes are defined in code. There is no Visual Class Library. However, if the class is a form you can use the Form Designer to build it visually; and if it's a user control, you get a little container in which your control component or components appear.

The use of namespaces is confusing to FoxPro developers. Namespaces are just there to add an additional level of naming. For example, the class library shown in Listing 1.3 defines two classes in Visual Basic .NET. Note that the project name for this class library is NameSpaceDemo . This is important because the name of the project is the default name of the generated DLL, which becomes the first part of the class name.

Listing 1.3. Namespace Declarations
 Imports System.IO Namespace PinterConsulting     Public Class Functions         Private _FileName As String         Private sep As Char         Public Property FileName()             Get                 Return _FileName             End Get             Set(ByVal Value)                 _FileName = Value             End Set         End Property     End Class     Public Class Objects         Public Class Person             Private _FirstName As String             Private _LastName As String             Private sep As Char             Public Property FirstName() As String                 Get                     Return _FirstName                 End Get                 Set(ByVal Value As String)                     _FirstName = Value                     Select Case _FirstName                         Case "Bob"                         Case "Fred"                         Case "Eddie"                         Case Else                     End Select                 End Set             End Property             Public Property LastName() As String                 Get                     Return _LastName                 End Get                 Set(ByVal Value As String)                     _LastName = Value                 End Set             End Property             Public ReadOnly Property FullName()                 Get                     Return FirstName + " " + LastName                 End Get             End Property         End Class     End Class End Namespace 

I've added a form in the same project that uses the classes. Notice that because the project name was NameSpaceDemo and the NameSpace was PinterConsulting, the name for the Imports statement (which is like SET CLASSLIB ... ADDITIVE ) is the concatenation of the two. Listing 1.4 shows the form code:

Listing 1.4. Using a Namespace in an Imports Statement
 Imports NameSpaceDemo.PinterConsulting Public Class Form1     Inherits System.Windows.Forms.Form     Dim NameMgr As New PinterConsulting.Objects.Person     Private Sub Form1_Load( _      ByVal sender As System.Object, ByVal e As System.EventArgs) _      Handles MyBase.Load     End Sub     Private Sub txtFirst_TextChanged( _      ByVal sender As System.Object, ByVal e As System.EventArgs) _      Handles txtFirst.TextChanged         NameMgr.FirstName = txtFirst.Text         Label1.Text = NameMgr.FullName     End Sub     Private Sub txtLast_TextChanged( _      ByVal sender As System.Object, ByVal e As System.EventArgs) _      Handles txtLast.TextChanged         NameMgr.LastName = txtLast.Text         Label1.Text = NameMgr.FullName     End Sub     Private Sub txtFileName_TextChanged( _      ByVal sender As System.Object, ByVal e As System.EventArgs) _      Handles txtFileName.TextChanged         Dim o As New PinterConsulting.Functions     End Sub End Class 

Note that I could have left out the Objects class because it only contains one nested class. But I could have added more classes within Objects , and they would also have been exposed via IntelliSense.

This is why I say that IntelliSense is merely nice to have in FoxPro, but in Visual Basic .NET you'd be dead without it. But I can imagine complex projects that need namespaces to document functionality of class members and classes, and it's just a naming convention. I just can't escape concluding that FoxPro works just fine without namespaces and wouldn't be enhanced if we had them. I understand the theory, but isn't anyone else out there cognizant of the divergence between theory and reality, and gutsy enough to eschew the theory?

Instantiating objects in Visual Basic .NET

One thing that will come up constantly in .NET is the creation and use of objects based on .NET classes. For example, the following code opens a table and displays its contents in a datagrid (the .NET equivalent of FoxPro's BROWSE):

 

 Dim cn As New SqlConnection("Server=(local);Database=Northwind;UID=sa;PWD=;") cn.Open() Dim da As New SqlDataAdapter("SELECT * FROM CUSTOMERS", cn) Dim ds As New DataSet da.Fill(ds) DataGrid1.DataSource = ds.Tables(0) 

The statement Dim cn As SQLConnection is like FoxPro

LOCAL cn As String

It doesn't create the variable. It just announces your intention to do so at some future date. Sounds goofy, but it's true. (It actually feeds IntelliSense - in both cases.) It's supposed to be followed by the statement that actually creates the variable. It can either be done with a New statement, or by referring to a member of an existing object. If you leave out the word New in the Dim cn statement above, you won't be able to pass the connection string in as a parameter. In the fourth line of the same code, you can leave out the word New without incurring a syntax error, but the following line will bomb because Fill only works with an existing Dataset, and the statement Dim ds As Dataset doesn't create one “ it only declares one.

Property Procedures in Visual Basic .NET

For years , Visual Basic developers got used to the idea of trapping the assignment of a value to a property and doing something when that assignment occurred. For example, I used to use a communication package that used the following syntax to read data from a telephone line:

 

 OModem.Setting = 14 OModem.Action = 4    ' Read 

The way this worked was that the moment of assigning a value to a property was trapped in what is called the Property Set method. At that instant, other code can be called. So they used that when they couldn't declare a "Do-it" method. It was a workaround for Visual Basic's inability to give us any way to simply write oModem.Read . After a while, the workaround seemed normal. Goofy but true.

The tradition continues. If you type

 

 PUBLIC PROPERTY FullName AS String 

and press Enter, Visual Basic will add complete the routine by adding the following six lines of code:

 

 Public Property FullName() As String     Get     End Get     Set(ByVal Value As String)     End Set End Property 

You have to add three more lines of code, one before the routine and two within it, to end up with this:

 

 Private _FullName As String Public Property FullName() As String     Get        Return _FullName     End Get     Set(ByVal Value As String)        _FullName = Value     End Set 

If you have two properties, you'll have two of these. If you have 20 properties, you'll have 20. Notice that a separate private variable (by convention the name is the property procedure's name preceded by an underscore ) is required in order to store the value manipulated by the property procedure, and it must be declared outside of the property procedure.

This is the equivalent of the Assign and Access methods that FoxPro allows you to create when you add a property to a class. As you may know, you can add code to the Assign method code to do other tasks when the property is assigned a value. That's the idea behind property procedures.

However, in Visual FoxPro property procedures (that is, Assign and Access methods) are completely optional; I've only had occasion to use them twice in years of client development.

In Visual Basic .NET, you can't see either class properties or public class variables in the Properties sheet for the class. However, you can't see public class variables in the Properties sheet. And you can only see them in subclasses that inherit from your classes. That's right; to get what you call a property in FoxPro, you must create a public property procedure in Visual Basic .NET. Strange but true. So even if you don't need the Assign and Access methods (called Getters and Setters in Visual Basic), you need property procedures. The fact that Visual Basic writes most of the code diminishes the pain, but I think it's goofy, and hope that it will be replaced by FoxPro's much simpler and clearly adequate counterpart some day.

Forms

Forms are classes in Visual Basic .NET. If you refer to one in a menu, it will take either two or three lines of code to display the form:

 

 Dim frm as new CustomerForm    ' can be written as 2 lines of code Frm.Show 

In FoxPro you just write

 

 Do form Customer 

However, have you ever looked at the structure of an SCX file? It has exactly the same structure as a VCX file. And in fact, if you save a form as a class, the code to run the form changes to this:

 

 Frm = CREATEOBJECT ( "FormClassName", "VCXFILE.VCX" ) Frm.Show() 

So they're more similar than you might have thought.

Forms have a section of code called the "Windows Form Designer generated code." When you're in the form designer, things that you do, like adding controls on the form, moving things around, and assigning values to properties, are actually stored in source code. The designer merely uses this code to create a visual display of the code's contents. If you manually change this code, it will be overwritten whenever a change is made in the designer and the file is saved.

However, sometimes it's useful to write code that is saved as part of the form's initialization sequence “ for example, using property values to open tables and populate some standard controls. If you have such code, you can place it in the Public Sub New() method, after the word InitializeComponent(). It's the only place in the Form Designer generated code that you can include code that won't be overwritten by the designer.

 <  Day Day Up  >  


Visual Fox Pro to Visual Basic.NET
Visual FoxPro to Visual Basic .NET
ISBN: 0672326493
EAN: 2147483647
Year: 2004
Pages: 130
Authors: Les Pinter

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net