Hi Robert,
most of the questions already have been answered.
2) The FoxPro class syntax speaks of "
Properties" and not of "
Fields" or "Instance variables"
Code: Select all
DEFINE CLASS ClassName1 AS ParentClass
[[PROTECTED | HIDDEN] PropertyName1, PropertyName2 ...]
[[.]Object.]PropertyName = eExpression ...]
What would you expect that happens when this is compiled to .Net. Should PropertyName1 etc. become a 'real property' (with a getter and setter) or should they be compiled into a Field.
The problem with compiling it to a field is that we sometimes see a syntax like this:
Code: Select all
DEFINE CLASS Animal as custom
Species = "Animal"
ENDDEFINE
DEFINE CLASS Dog AS Animal
Species = "Dog"
ENDDEFINE
If we compile "Species" to a field then the Dog class will try to redefine the field in the parent class.
Our compiler will then produce the warning:
Code: Select all
warning XS0108: 'Dog.Species' hides inherited member 'Animal.Species'. Use the new keyword if hiding was intended.
From what I have seen FoxPro declares everything as "real" properties and somehow stores name/value pairs in an invisible collection inside each object and both Species in the Animal class and in the Dog class read/write from the same collection. So all these properties are virtual as well
So my current thinking is to generate .Net properties from this and make these virtual so they can be overwritten in a child class. We can also add a collection, but we can also create a backing field. In case of a property that overrides a parent property we can change the getter and setter and redirect the call to the parent property.
But that would mean that you can't create fields with the current FoxPro syntax.
I see a couple of solutions:
a) with a special compiler option you can tell the compiler to generate fields or properties. When you generate fields you will get a warning when you redefine a field in subclass
b) we always generate properties but add a special syntax to declare fields, something like
Code: Select all
DEFINE CLASS ClassName1 AS ParentClass
[[PROTECTED | HIDDEN] FIELD Field1, Field2 ...]
FIELD FieldName = eExpression ...]
Btw: our current definition allows you to specify the types for Fields/Properties:
Code: Select all
[[PROTECTED | HIDDEN] PropertyName1, PropertyName2 ...] [AS DataType]
I envision Foxpro "Classes" to work more like Javascript prototypal inheritance, only castrated insofar as you cannot access, redirect and/or monkeypatch the prototype hierarchy.
Consider:
Code: Select all
clear
=test(.f.)
=test(.t.)
? "Does not look unreasonable..."
clear ALL
release All
? "And Now for Something Completely Different"
? "Proof: Wolf reads prototype Mammal, Poodle reads prototype Dog"
=test(.t.)
FUNCTION test(tlFlag)
local laClassNames[1], lcClasses, lnCnt, lnRun
lcClasses = "mammal,canine,wolf,dog,poodle"
lnCnt = alines(laClassNames, m.lcClasses,5,",")
for lnRun = 1 to m.lnCnt
= choir(laClassNames[IIF(m.tlFlag, m.lnRun, m.lnCnt+1-m.lnRun)])
next
FUNCTION choir(tcClass)
local loSinger, lcSound
loSinger = CREATEOBJECT(m.tcClass)
lcSound =loSinger.bark()
wait window m.lcSound timeout 2
? m.lcSound
define CLASS mammal as Custom
cSound = "meeep"
nProto = SECONDS()
nInitM = 0
FUNCTION Init()
this.nInitM = SECONDS()
FUNCTION bark()
return STR(this.nProto, 12,3) ;
+ STR(this.nInitM, 12,3) ;
+ " : " + this.Class
ENDDEFINE
define CLASS canine as mammal
cSound = "wuff"
ENDDEFINE
define CLASS wolf as canine
cSound = "hoooowl"
enddefine
define CLASS dog as canine
nProto = SECONDS()
enddefine
define CLASS poodle as dog
cSound = "wack"
enddefine
As most of Javascript shenanigans like mixins, monkeypatching and so on are disabled in vfp so that classic inheritance is mirrored closely, go for the code compiling to the fastest IL
3) All methods inside FoxPro seem to be virtual. This was also the case for Visual Objects. We have a compiler option that does this automatically.
4) The ADD OBJECT syntax creates a property (field?) and sets the value of the property to a new object of the specified type and allows to set initial values for some properties of this new object. What is not clear to me is if this object is also automatically added to a collection of children (controls) in the class ?
Addproperty() function and method add a name to the NTI of the object, which can be filled with any vfp data type, including objects.
ADD OBJECT and .addobject() add an object to the name, set .parent property in the abject to be added (build a "container" hierarchy) and add the same object ot the .objects collection. I am 90% certain that there is only 1 such collection in each container class, which you can access via .objects in all containers and via another property, named after the "possible" class type ("Controls" for Form and container, "Buttons" in Commandgroup and Optiongroup, "Pages" in Pageframe and so on.
I have never checked if those 2 names point to the same collection or if I can tweak them differently - I saw never a real reason for having either 2 names/pointers and an identical collection or 2 different collections....
ADD OBJECT and .addobject() added objects get their destroy called automatically, objects added via addproperty needing their .destroy to be manually called to prevent memory leaks (if linked ito other structures...) must be handled in code.
The special containers for a single GUI class control the # of their children via special ????count properties having assign methods- increasing them calls .addobject on the .memberclass [ ¦ of .memberclasslibrary].
5) Now that we move FoxPro to .Net we will also be able
add new functionality. So far we have added the following (for free because it is there in our compiler already)
- The ability to declare attributes on a type, property method etc
- The ability to add more (visibility) modifiers then just PROTECTED and HIDDEN. For example also INTERNAL,ABSTRACT, STATIC and SEALED
- The ability to define Generic types and methods
Code: Select all
DEFINE CLASS MyStack<T> WHERE T IS NEW()
- All types can be specified in the Namespace.Type syntax. For example
Code: Select all
CLASS MyTable as System.Data.DataTable
I saw in Johans code that in other dialects you can assign methods like
Code: Select all
CLASS MyFirstXSharpForm INHERIT Form
CONSTRUCTOR()
SUPER()
Size := Size{100, 100} // Check if it is not dimension, out of top of my head
Text := "My first XSharp Form"
VAR btn := Button{}
btn:Text := "Close"
btn:Location := Point{5,5}
btn:Click := MyButtonClick // what the click event will fire
SELF:Controls:Add(btn)
RETURN
METHOD MyButtonClick(o AS OBJECT, e AS EventArgs) AS VOID
SELF:Close()
RETURN
END CLASS
Assigning functions/methods and perhaps passing the function itself, not the result as parameter are already things tempting me to switch - I see the benefit of such constructs in Javascriot and Python. Vfp as a language has grown only minimally and shows its age, although it gained at least some modern ideas in eventbinding and Cursoradapter. And it would be nice to tweak the speed without going down into C - I am too old for that. You already have quite a lot - but IMO the real test for the vfp runtime will be in the area of
-set("buffermode"), set("datasession"), sys(3054)
-functions tableupdate/tablerevert, getfldstate, cursorset/getprop, getcursoradapter, curval, oldval, sqlset/getprop
-objects session, cursor, datasession and cursoradapter (I prefer them to remote views)
-Solid SQL on disc-based tables(dbf, cursor, view)
-including basic optimizer able to create missing indices on temp results of multiple joins and bitmap speedup
-most of last decades SQL server in the SQL language scope except CTE and merge/upsert logic (- but no real Replication)
as that is IMO the special sauce in vfp not found in any other language - using client disc as SQL cache to minimize network calls.
Use ANY SQL server as RW datastore,
mix in RO data kept locally via SQL as biz layer with the ability to persist or throw away local changes
bind to any GUI with a well layered architecture but still without the need to employ ORM for your data
Also almost all tools make extensive use of local tables, often via SQL.
my 2.22€ (have thought about this for some time...)
thomas