|
TUTORIAL - OBJECTS |
Previous | Next | Tutorial Home |
FGL supports standard and enhanced objected-oriented methodologies. In general, classes
represent container definitions that can include any combination of data and (typically)
related functions within a single entity. Objects are specific instances of defined classes.
For example, a class entitled “dogs” may have object instances of “beagle”, “shih-tzu”,
and “poodle”. In turn, the class “dogs” may be a subclass of “animal”.
Objects and Classes can contain data, functions, or both. Likewise, FGL supports a number
of advanced objected oriented programming (OOP) concepts that include visibility, scope,
polymorphism, and inheritance.
<[
// define the class
CLASS objDOG
local name, breed, sex, age, color, size
END
]>
<html>
<head>
<title>Simple object example</title>
</head>
<body text=black bgcolor=white>
<[
// create an object instance of the objDOG class
dog = new( "objDOG" )
// assign values to the dog object
dog.name = "Cosmo"
dog.breed = "shih-tzu"
dog.sex = "M"
dog.age = 2
dog.color = "black and white"
dog.size = "small"
// now use the object data
! "The dog is a " + dog.breed + " and " + ( upper( dog.sex ) == "M" ? "his" : "her" )
! " name is " + dog.name + ", which is a " + dog.size + " dog. "
! dog.name + " is " + dog.color + " and is " + dog.age + " year(s) old."
]>
</body>
</html>
|
Objects and classes make it very easy to create containers of related information and
the processes that work on the information. In the following example, the objContact class
contains a number of public variables: fname, lname, street, city, state, zip, and country.
PUBLIC variables in a class are accessible outside of the class. Variables with the PRIVATE
designation are only available within the class. The object also includes several ACCESS
variables, including: fullname and MailingLabel. Access variables are treated the same as
public variables outside of the class, however inside the class the are treated as virtual
variables whose values are determined based on the instructions associated with the access
variable definition. For example:
<[
CLASS objContact
PUBLIC:
local fname, lname, street, city, state, zip, country
ACCESS fullname
return( self.fname + " " + self.lname )
END
ACCESS MailingLabel
local str=""
str += ::fullname + "<br>"
str += ::street + "<br>"
str += ::city + ", " + ::state + " " + ::zip + "<br>"
str += ::country
return( str )
END
END
]>
<html>
<head>
<title>Object example</title>
</head>
<body text=black bgcolor=white>
<[
contact = new( "objContact" )
contact.fname = "Angela"
contact.lname = "Repetti"
contact.street = "600 N Pine Island Rd, Suite 350"
contact.city = "Plantation"
contact.state = "FL"
contact.zip = "33324"
contact.country = "USA"
! contact.fullname + "<br><br>"
! contact.MailingLabel
]>
</body>
</html>
|
Note the use of “self” and “::” operators in the prior example. Both are used to
reference data, access variables, and methods within the class and are designated as
“self” (similar to the JavaScript "this" reference) regardless of the notation. You may use
either one interchangeably, however "::" is two characters less typing than "self".
Objects can also include embedded functions, known as METHODS. These operate much the
same way as functions, but have full access to all of the data, access variables, and other
methods within the class. The NEW method is a special method which is automatically called
whenever an object instance of a class is created. This gives the object the opportunity to
initialize or perform any required setup or configuration before it is used.
<[
CLASS objDOG
local name, breed, sex, age, color, size
METHOD new( a )
// make sure data is passed in as an array
// otherwise create a default "empty string" array
a = type( a ) == "A" ? a : { "", "", "", "", "", "" }
::name = a[1]
::breed = a[2]
::sex = a[3]
::age = a[4]
::color = a[5]
::size = a[6]
return( 1 )
END
END
CLASS MyDogList
local aData
METHOD new( )
::init( )
return( 1 )
END
METHOD init( )
local a, cnt, i
a = ::aRawData
asort( a, 0, 1 )
cnt = len( a )
for ( i=1; i<=cnt; i++ )
::aData[i] = new( "objDog", a[i] )
end
return( 1 )
END
ACCESS aRawData
static a = {
{ "Cosmo", "shih-tzu", "M", 2, "black and white", "small" },
{ "Merlin", "beagle", "M", 15, "black, white, and brown", "medium" },
{ "Hoss", "Kentucky-dog", "M", 4, "white", "small" },
{ "Elvis", "hound dog", "M", 2, "brown and white", "large" },
{ "Pixie", "teacup yorkie", "F", 1, "brown and grey", "very small" },
{ "MindyLou", "pomeranian", "F", 1, "brown and grey", "very small" }
}
return( a )
END
ACCESS HowManyDogs
return( len( ::adata ) )
END
METHOD NameMyDogs( )
local cnt, i, str="", obj
cnt = ::HowManyDogs
for ( i=1; i<=cnt; i++ )
obj = ::aData[i]
str += obj.name + "<i>: the " + obj.color + " " + obj.breed + ".</i><br>"
end
return( str )
END
ACCESS AverageAge
local cnt, i, ttl=0
cnt = ::HowManyDogs
for ( i=1; i<=cnt; i++ )
ttl += ::aData[i].age
end
return( int( ttl / cnt ) )
END
END
]>
<html>
<head>
<title>Advanced object example with methods</title>
</head>
<body text=black bgcolor=white>
<[
mydogs = new( "MyDogList" )
! "I have " + mydogs.HowManyDogs + " dogs.<br><br>"
! "Their names are:<br>"
! mydogs.NameMyDogs( ) + "<br>"
! "Their average age is " + mydogs.AverageAge + " years old."
]>
</body>
</html>
|
In the above example, an object instance of the “MyDogList” class is created. This
automatically calls the NEW method within the class which in turn calls the “::init( )”
method. The init method creates multiple instances of the “objDog” class from a data array
within the class and stores them in an array of objects (::aData) within the MyDogList
object. Note that when the objDog objects are created the data is also passed as a
parameter (in the form of a multi-dimensional array) to the NEW method of each objDog object.
FGL includes internally predefined engine classes, such as the session object, as well
as externalized FGL libraries containing functions and class definitions. The SYSTEM.FLB
library includes a large collection of useful functions and classes that can be incorporated
into your program by referencing the library. The source code for SYSTEM.FLB is also
available.
<[
LIBRARY \fgl\libs\system.flb
session = new( "session" ) // internal class
html = new( "objHTML" ) // system.flb class
]>
<html>
<head>
<title>Object example using libraries</title>
</head>
<body text=black bgcolor=white>
<[
! html.notice( "HTTP Header Data:", session.data( "ALL_HTTP" ) )
]>
</body>
</html>
|
FGL classes provide support for ACCESS and ASSIGN methods for use in the creation and
interaction of virtual variables. Virtual variables look and act just like any other class
variable outside of the class, however inside the class the ACCESS method is used to get
the value of the virtual variable and the ASSIGN method is used to set the value.
Additionally, FGL classes support default handlers for ACCESS and ASSIGN variables as
well as for METHODS themselves. If defined within a class, these are called when a variable
or method is referenced that otherwise does not exist.
FGL classes also support operator overloading, which is useful for creating extremely
advanced and customized classes and object interaction. Operator overloading lets you define
how the object behaves during operations, such as addition, subtraction, multiplication, and
more.
<[
LIBRARY \fgl\libs\system.flb
CLASS objDefaultExample
PUBLIC:
INHERIT objFromArray
METHOD new( a )
::a = a
return( 1 )
END
OPERATOR + ( var )
switch ( type( var ) )
case "O"
return( ::fname + " and " + var.fname + " forever" )
case "C"
return( ::fname + " and " + var + " forever" )
default
return( "unknown handler" )
end
END
END
aAngie = {
{ "fname", "Angie" },
{ "lname", "Repetti" },
{ "title", "Director of Operations" },
{ "phone", "555-473-6868" }
}
aSteve = {
{ "fname", "Steve" },
{ "lname", "Repetti" },
{ "title", "CEO/Chief Technical Officer" },
{ "phone", "555-473-6868" }
}
obj1 = new( "objDefaultExample", aAngie )
obj2 = new( "objDefaultExample", aSteve )
]>
<html>
<head>
<title>Advanced object example using inheritance, default handlers, & overloading</title>
</head>
<body text=black bgcolor=white>
<[
! obj1.fname + " " + obj1.lname + "<br>"
! obj1.title + "<br>"
! obj1.phone
! "<br><br>"
! obj2.fname + " " + obj2.lname + "<br>"
! obj2.title + "<br>"
! obj2.phone
! "<br><br>"
! obj1 + obj2 + "<br>"
! obj1 + ( obj2.fname + " " + obj2.lname ) + "<br>"
]>
</body>
</html>
|
In the above example, a minimal class “objDefaultExample” is defined that includes a
single INHERIT statement, NEW method, and OPERATOR overload handler. The INHERIT statement
causes all of the components of the “objFromArray” class to be available from with the
objDefaultExample object. The objFromArray class is defined in the SYSTEM.FLB library with
source provided in the OBJECT.FGL file.
The objFromArray class essentially provides a virtual class wrapper around a
two-dimensional array of name/value pair data. This is accomplished by using the default
ACCESS and ASSIGN methods within the objFromArray class to handle interaction with the data.
The NEW method in the objDefaultExample class is passed the two-dimensional array to a
variable identified as “::a”. This is not in the class itself, but is inherited from the
objFromArray. This in turn is an ASSIGN method that takes the array, sorts it, and stores
it within the class.
The OPERATOR overload handler for the addition operator (+) allows the objects to be
added together in unique ways. Furthermore, this handler uses the type( ) function to
determine the type of data being added so that it behaves differently depending on whether
a string was added or another object.
Obviously this is a rather single-purposed example that would require additional error
handling for the various combinations of information that could be processed.
#####
|