Operator Assignment/Convert

Hello,

I’ve some problems with the concepts of Operator Overloading, especially for the assignment.
I need objects, which represents coordinates in my system. For a 2D-case my class would have params Integer x and Integer y.
Now, I want to use the operator overloading, to have a nice coord1 + corrd2 = coord3. This works very nice for arithmetic operators.
But one big problem arises, when passing these coordinates around. For example following code:

Dim new_coord As Coordinate(1,2) // initializes new_coord.x=1, and .y=2
Dim old_coord As Coordinate = new_coord // now, old_coord.x=1 and .y=2
new_coord.x = 3 // oups, now old_coord.x is also 3

For this it would be nice, to have some copy-constructor (Yeah, I’ve learned, not to use foreign features to Xojo, but… :slight_smile: )

So is it possible to have something like

Sub Coordinate.Operator_Convert(Assigns l_coord As Coordinate) // copying the values byval

or is it still possible to use the Operator_Convert between two identical types and I wrote some misbehaviour? :

Sub Coordinate.Operator_Convert(l_coord As Coordinate) // copying the values byval
//or
Sub Coordinate.Operator_Convert() Coordinate

(When Debuggin, Xojo simply ignores the last both lines)

I know that the stupiest solution would be to introduce a Coordinate.set function, where I can do this by hand, but the Assignment-Operator would be very nice to have.

Thanks you a lot!

Well, you are not assigning the VALUES to an instance (the old one in your case), but assigning the new INSTANCE to the old VARIABLE, ending up with two variables (new_coord and old_coord) pointing to the same INSTANCE, while the other instance gets removed from memory (given that there’s no other other pointer to it). That means, if you manipulate the properties of the instance through one variable, the second one will apparently mirror that since it refers back to the very same instance.

You won’t be able to do what you want with the operator overloading methods. A dedicated shared method is the way to go. Create a new shared method that takes an instance of the class as a parameter. Have the method create a new instance of the method, assign the values from the passed instance to the newly created one and return the new instance.

Then you would write something like:

Dim old_coord As Coordinate = Coordinate.Copy(new_coord) //or whatever your shared method is called

On a side note: your first line seems wrong to me as well. You cannot call a constructor (in your case Coordinate(1,2)) without creating a new instance through the NEW keyword. Instead, it should be something like:

Dim new_coord As New Coordinate(1,2)

Addition: of course you can do a copy-constructor!
Just have a method called constructor that takes an instance of your class as a parameter and assign the passed instance’s properties to the new instance’s properties.

Than you can do things like:

Dim cord1 as NEW coordinate(1,2) Dim cord2 as NEW coordinate(cord1)

Thank you Alex,

  1. [quote]On a side note: your first line seems wrong to me as well. You cannot call a constructor (in your case Coordinate(1,2)) without creating a new instance through the NEW keyword. Instead, it should be something like:

Dim new_coord As New Coordinate(1,2)[/quote]

Yeah you are right - luckiliy that Xojo would have warned me :wink:

  1. [quote]Then you would write something like:

Dim old_coord As Coordinate = Coordinate.Copy(new_coord) //or whatever your shared method is called[/quote]
so I have to write my set-function

All in all this is a little bit confusing from my point of view, especially logically - I can override every possible Operator which can fullfill every algebraic axiom, expecting the simpliest - which is, when dealing with default-byVal-params, the most important to overcome the referenceness, or?

  1. [quote]

Addition: of course you can do a copy-constructor!
Just have a method called constructor that takes an instance of your class as a parameter and assign the passed instance’s properties to the new instance’s properties.

Than you can do things like:

Dim cord1 as NEW coordinate(1,2)
Dim cord2 as NEW coordinate(cord1)[/quote]
But this wouldn’t help me for my problem or?

[quote=290933:@Hans Jochen Steffen]
2.
so I have to write my set-function

All in all this is a little bit confusing from my point of view, especially logically - I can override every possible Operator which can fullfill every algebraic axiom, expecting the simpliest - which is, when dealing with default-byVal-params, the most important to overcome the referenceness, or?[/quote]

I think the confusion lies in the level of hierarchy. It is true that Xojo uses “=” for both assignment and comparison. You can do assignments on different levels. For example:

Dim v1 As New myClass Dim v2 AS New MyClass v1.property1 = v2.property1

That will assign the value of property1 of the instance referred to by v2. If the property is not defined, you could use operator overloading to overload the assignment on the level of the class.

However, in the case of

Dim v1 As New myClass Dim v2 AS New MyClass v1 = v2

you do not act on the level of the class/instance. You just assign a reference to an instance to a local variable. Do you know, what I want to explain? Operator overloading would be one level further down.

[quote=290933:@Hans Jochen Steffen]
3.
But this wouldn’t help me for my problem or?[/quote]

If I understood your concern correctly, it should be the best solution IMHO.

Have two constructors for your Coordinate class:

Sub Constructor(x as integer, y as integer) self.x = x self.y = y End sub

Sub Constructor(c as Coordinate) self.x = c.x self.y = c.y //of course you should do error checking etc End sub

Now you can do:

Dim c1 As New Coordinate(1,2) //creating a new instance with constructor 1 Dim c2 As New Coordinate(c1) //creating a new instance with copy constructor 2, now we have two individual instances with the same data c1.x = 20 //c2.x shoud still be 1

(Disclaimer: all code written from the top of my head and thus not tested for syntax errors.)

Quick example project :slight_smile:
https://dl.dropboxusercontent.com/u/106712747/CopyConstructorExample.xojo_binary_project

Yeah, thank you again!

[quote]However, in the case of

Dim v1 As New myClass
Dim v2 AS New MyClass
v1 = v2

you do not act on the level of the class/instance. You just assign a reference to an instance to a local variable. Do you know, what I want to explain? Operator overloading would be one level further down.[/quote]
Thats maybe my problem, because I can overload every other operator a level further down, expect for the assigment operator.
I can explicitly write a function like operator_add(Dim v2 as myClass) myClass, but not operator_convert(Dim v2 as myClass) myClass. I even can write somtehing like operator_convert(Dim v2 as myNewClass) myClass… so everything is possible in any hierachy-layer for every combination, expect the simple assignment :slight_smile:

But then, I’ll stick to that ugly duckling by adding a explicit function to assign-and-copy it and write some good manual, so that no user will ever try to assign a value directley and run into long bug-hunting

[quote=290937:@Hans Jochen Steffen]Yeah, thank you again!

Thats maybe my problem, because I can overload every other operator a level further down, expect for the assigment operator.
I can explicitly write a function like operator_add(Dim v2 as myClass) myClass, but not operator_convert(Dim v2 as myClass) myClass. I even can write somtehing like operator_convert(Dim v2 as myNewClass) myClass… so everything is possible in any hierachy-layer for every combination, expect the simple assignment :slight_smile:

But then, I’ll stick to that ugly duckling by adding a explicit function to assign-and-copy it and write some good manual, so that no user will ever try to assign a value directley and run into long bug-hunting[/quote]

Right. When writing v1 = v2 you are not manipulating an instance, but the variables pointing to them. That’s not a limitation as such but rather the correct design. Otherwise, how would you be able to assign an instance from one var to another one? :slight_smile:
Instead of going down the way of the extra method just give the constructor example a try (see project link I posted above). That’s the most proper design IMHO.

Hihi, recently this is my problem I wrote in my first post - I’ld like to say that this assignment should be a hard-copy instead of some pointer/reference-gymnastics to prevent some errors*; not to produce some. Manually I can do both ways, copy an instance (because its byref by default) and copy content of the instance, but this design ‘feature’ is a little bit missleading…

*Can’t remeber, but how are those bugs called, I was creating? Copying only pointers and not the content and you dont find the reason for it anymore? I think that would have been a good reason to implement this operator overloading, or? I mean this deep/shallow-copy problem exists since a long time

In my opinion that would be an absolute nightmare to code if we changed the behaviour of the = operator from assigning to copying instances. Most often you don’t want to get a copy but just do some magic to an existing instance (not, we’re talking about the assignment operator, not passing values to methods which is an entirely different story w/ regards to byval and byref). I don’t know any language that does this…

Currently, there’s no native way to generically copy a class instance in Xojo. There’s been an ongoing debate (feel free to read the numerous threads in the forums…) about that. Some tried to implement such serialisation/deserialisation using introspection, although that is likely to result in more headache. I believe there are a number of related feature requests in Feedback.

IF Xojo was to implement such a feature, I’d rather have them add a new operator for copying instances instead of changing the assignment operator’s behaviour. E.g. keep = for assignments and add ? for cloning.

No, I’ld rather prefer, to have the ability to override the =operator, when I use the same data-type (What is possible for every combination, expect this special case). The default behaviour is obvious quite useful - but to complete to set of operator-overridings… It’s now like some imperfect.

It’s a little bit hard to gain progress in this language when there are so many exceptions - it’s like the overloading for the return values, what is the rule, that the linker does not distinguish between the return-values except for the constructor? (I think that was the correct example).
By the way - is there any document for how the linker works? It would help me very much…

There is a lot of non-“with no loss of generality” in Xojo :slight_smile:

[quote=290948:@Alex von Siebenthal]IF Xojo was to implement such a feature, I’d rather have them add a new operator for copying instances instead of changing the assignment operator’s behaviour. E.g. keep = for assignments and add ? for cloning.
[/quote]
I can’t see that ever happening. Duplicating a single object would be a simple thing, but what about a class which contains other object properties (simple ones like dates, or complex ones like other classes with multiple objects). Should the cloned object properties refer to the same object as the original property, or should it be a clone of the original? That’s something that the programmer would really need to determine in each case.

Using a separate operator (or changing functionality of the = operator) might work for dates and such, but not for complex classes.

Many OOP languages do not support that (C++, C#, VB .NET, etc.). The reason is that with a statically typed programming language it is difficult to parse (for example Java does not support it too, but the Java Virtual Machine does).

The default behavior is the only correct thing in that case. Changing that – I must second Alex on this – would be a nightmare. Maybe not immediately, but in the long-term your better off with an instance method Copy or Clone.

[quote]Many OOP languages do not support that (C++, C#, VB .NET, etc.). The reason is that with a statically typed programming language it is difficult to parse (for example Java does not support it too, but the Java Virtual Machine does).[/quote] Oh, I mentioned it more for the example of the generality - otherwise, it is done by templates, I think.

Nja… the only correct thing - why should I use then assigments with other values, expecting the class itself? I mean, I can undergo it by creating a inherit class and work with this, but this then looks a little bit helpless. When I am able to overload the ‘=’ as a converting operator but not as an assigment operator…oh no…that works also with the assigend keyword… so If I want it overwritten explicitly - why can’t I in this special case?
As a creator of classes I’m responsible of the operators and therefore, I can’t see no nightmare if I manipulate this with my full intention (Not more than any other method.). But without the possibilty I’m limited to tell the users “Oh, be careful, don’t use the assigment, use the clone()-operator instead, but otherwise this is a fully set of mathematic operator which with u can operatore…” . And - knowing the concepts of pointers - there shouldn’t be any difficult in understanding it. And it would complete the syntax for the sake of completness (if this is not wanted, I can’t help) - and Xojo seems a little bit un-finished to me…

It is a good rule to write an API or a library the way the programming language is intended to be used. So, yes, it would be a nightmare when one class does not do an assignment operation of a reference type as expected by the user of the library. Note that all other classes are behaving identical and this one class would introduce an unknown behavior.

Exactly, every Xojo user of that library doing an assignment operation of a Coordinate instance to a second variable would expect that it points to the same instance in the heap.

This is not an argument. There is no “completeness” to achieve here. What does Operator_Convert has to do with mathematical operators or Operator_Lookup?

The issue here is one of understanding the difference between an VALUE types and REFERENCE types

An integer holds the value directly - there’s no pointer (or reference) required.

A type that you use NEW with is basically a pointer to the data that makes up the instance.

When you assign a VALUE type it copies that value
So code like

     dim i, j as integer
     i = 3  // the memory location for I holds the value 3
     j = i // the memory location for j is assigned the value held in the memory location for i

For a reference type its quite similar

     dim i, j as Date
     i = new Date  // the memory location for I holds the ADDRESS of the memory set aside for the new date
     j = i // the memory location for j is assigned the value held in the memory location for i

BUT note that there is NO second copy of the date for j in the second example
And the reason is … NEW is NOT called

But its easy enough to add a copy constructor to your class then write your code as

Dim new_coord As Coordinate(1,2) // initializes new_coord.x=1, and .y=2
Dim old_coord As Coordinate = new Coordinate(new_coord) // invoke copy constructor
new_coord.x = 3 // oups, now old_coord.x is also 3