Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Name Property

Status
Not open for further replies.

vfp4ever

Programmer
Oct 18, 2013
71
East Java
Hello,

every few years I tend to revisit some basic concepts and still find unexpected behaviour that leaves me somehow doubtful. This time is about the Name property of a class:

Code:
LOCAL loObject AS Object
loObject = CreateObject( "MyContainerClass" )

DEFINE CLASS MyContainerClass AS Container
	ADD OBJECT MyObject_1 AS MyClass

	FUNCTION Init( ) AS Boolean
		WITH This
			? .MyObject_1.Class, .MyObject_1.Name

			LOCAL MyObject_2 AS Object
			MyObject_2 = CreateObject( "MyClass" )
			? MyObject_2.Class, MyObject_2.Name

			.AddObject( "MyObject_3", "MyClass" )
			? .MyObject_3.Class, .MyObject_3.Name
		ENDWITH

		RETURN .T.
	ENDFUNC
ENDDEFINE

DEFINE CLASS MyClass AS Session
*	Name = "MyName"
ENDDEFINE

This is what I get as results:
Code:
Myclass MYOBJECT_1
Myclass Myclass
Myclass MYOBJECT_3

and this is what I get if I uncomment the Name assignment within the definition of MyClass:
Code:
Myname MYOBJECT_1
Myname Myname
Myname MYOBJECT_3

My questions are:
1) Shouldn't the second line in the top results show "Myclass Myclass1" instead of "Myclass Myclass"?
VFP Help said:
The default name for new objects is the type of object plus a unique integer.
2) Why all Class properties are renamed to "Myname" in the bottom results (and the second line still shows "Myname" instead of "Myname1")?

Regards,
Dario
 
1. The help is forgetting to tell this is about objects you add into a visual designer. In there the object names are suffixed with a number, creating objects in code does not add numbers to the name.
So this is not a default and the names of objects are not necessarily unique. They only need to be unique as subojects of a parent object, which is the reason this suffixing is needed in the designers, otherwise which textbox should form.textbox be, if there are several?

2. When you set the name property within a define you really set the class name, not the name property, because the class definition is not an instance, it's the definition, the original of all the blueprints created later. At instance creation its name is copied as the instance name and also into the readonly class property of the instance and the designers suffix a number here. You can actually do harm in visual classes when you hack into the properties memo and set the name propety somewhere in there different from the name stored in the objname memo.

Make a third experiment and instead of simply setting Name in the class definition make it an assignmet in the init:

Code:
DEFINE CLASS MyClass AS Session
    Procedure Init()
        This.Name = "MyName"
    EndProc 
ENDDEFINE

You'll instantly have trouble, as even the object added via ADD OBJECT MyObject_1 AS MyClass will have the name MyName and addressing .MyObject_1.Class, .MyObject_1.Name errors. If you fix this you get a name conflict in the AddObject line trying to create MyObject_3.

So be cautious about the name property both in the class definition and in code. In the class definition the name determines the class name and should not contradict the name in the DEFINE CLASS line or the objname of the vcx main record of the class. For instances you better set the name via the name parameter of Addobject or the name of the ADD OBJECT clause and treat it as readonly property. This saves you from surprising behaviour and side effects.

Also don't use the name of things as a reference, you references via variables, code referencing forms via their name property is needed for legacy commands like HIDE WINDOW and SHOW WINDOW, which whould be avoided.

To ensure instance names not to collide in case you compose forms at runtime there are different strategies eg in the simplest case with unique names like sys(2015) provides.

Bye, Olaf.
 
Thanks Olaf,
your detailed explanation is always appreciated and welcome.

1) I see, it does make sense.

2) I have always avoided bothering with the .Name property at all, that is why I still get confused at times. As a matter of fact I still wonder why its name is copied into the .Class property. I suspect .Name could have been a candidate as a read-only property at runtime. So, again I will leave it buried in there for a while and ignore it as I have always done. :)

Thanks again,
Dario
 
2) The question rather is why the class name is stored in the name property and why there is no specific property for it. But the class property itself is always the class used to create this instance OR this class, so it's the parent class. It's even more irritating if you know the field names of vcx records.

Bye, Olaf.
 
When you drop, in the IDE, an instance of the MyClass, inside a container, you create a new object, member of the container.
Because "members" (like properties, contained objects) are identified by name, that object must have a unique name relative to the container.
The easiest way IDE can do that, is to concatenate the class name with a counter.

When you use ADD OBJECT in the DEFINE CLASS, you also create a new member of that class. Each member must have a unique name, and this unique name is provided by you, explicitly.

Almost identically happens when you use .AddObject(). Once again you created a new member of that class with a unique name, and this unique name is provided by you, explicitly.

No matter which one of the above three ways you use to add a member to a container, you've created a new member of the container. And because container members are identified by their name, each one must have a unique name, in the container context.

On the other side, CREATEOBJECT() function, creates an instance of a class, and return a reference to that object.
Because that object is not a member of some container, its name is irrelevant.
You access the object through its reference, not by its name.

Let's add a fourth object to MyContainerClass, by using the CREATEOBJECT() function.
I added a new property, MyObject_4, to store the reference returned by the CREATEOBJECT() function.
In this case, changing the object name has no side effect, because the "member" of the container is the property MyObject_4 (which contains a reference to that object), not the object itself.

Code:
LOCAL loObject AS Object
loObject = CreateObject( "MyContainerClass" )

DEFINE CLASS MyContainerClass AS Container
	MyObject_4 = .Null.	 &&&&&&&&&&&&&&&&&&&&&&&&&&
	ADD OBJECT MyObject_1 AS MyClass
	FUNCTION Init( ) AS Boolean
		WITH This
			? .MyObject_1.Class, .MyObject_1.Name

			LOCAL MyObject_2 AS Object
			MyObject_2 = CreateObject( "MyClass" )
			? MyObject_2.Class, MyObject_2.Name

			.AddObject( "MyObject_3", "MyClass" )
			? .MyObject_3.Class, .MyObject_3.Name
			
			.MyObject_4 = CreateObject( "MyClass" ) &&&&&&&&&&&&&&&&&&&&&&&&&&
			? .MyObject_4.Class, .MyObject_4.Name
			.MyObject_4.Name = "MyName"
			? .MyObject_4.Class, .MyObject_4.Name
		ENDWITH

		RETURN .T.
	ENDFUNC
ENDDEFINE

DEFINE CLASS MyClass AS Session
*	Name = "MyName"
ENDDEFINE

Respectfully,
Vilhelm-Ion Praisach
Resita, Romania
 
I wish to emphasize a little, what Olaf Doschke said about class names.

If you define two different classes with the same name, inside the same prg, VFP will not throw an error, but will use the last definition.
Code:
PUBLIC ofrm
ofrm=CREATEOBJECT("MyForm")
ofrm.show()

DEFINE CLASS MyForm as Form
	ADD OBJECT cmd as mycommand 
ENDDEFINE

DEFINE CLASS mycommand as commandbutton
ENDDEFINE

DEFINE CLASS mycommand as textbox
ENDDEFINE

If your class is renamed like a base class, you'll lose access to that base class, although VFP will not throw an error.
Code:
PUBLIC ofrm
ofrm=CREATEOBJECT("MyForm")
ofrm.show()

DEFINE CLASS MyForm as Form
	ADD OBJECT txt as mytextbox
	PROCEDURE txt.KeyPress
		LPARAMETERS nKeyCode, nShiftAltCtrl
		NODEFAULT
		textbox::keypress(nKeyCode, nShiftAltCtrl) && lose access to the base class
	ENDPROC
ENDDEFINE

DEFINE CLASS mytextbox as TextBox
	name="TextBox" && comment this and you gain access to the parent class
	PROCEDURE KeyPress
		LPARAMETERS nKeyCode, nShiftAltCtrl
		WAIT WINDOW "Parent class" TIMEOUT 1
	ENDPROC
ENDDEFINE

Respectfully,
Vilhelm-Ion Praisach
Resita, Romania
 
Thanks Vilhelm,

I had never thought about changing the name of a derived class into the original name... that was an interesting experiment indeed. I wonder how better it would be if VFP could throw a few more warnings here and there, and how better it would be if the whole language would have been case-sensitive (instead of having MYOBJECT_1, MyObject_2 and Myclass). Yet it remains the most beautiful.[love2]

Regards,
Dario
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top