Skip to main content

Operator overloading (again) and functions

131 replies [Last post]

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
kcpeppe
Offline
Joined: 2003-06-15
Points: 0

> Many who disagree with operator overloading keep
> quoting the example of C++. It's true that oo in C++
> was messed up, and I think it's mainly because of the
> way the C++ libraries like the stream io libraries
> were implemented:

OO in C++ is messed up because the langauge *has* operators! It has operators because not everything is an object. This means that you have strange things like if-then-else, switch and while statements. You have other very strange things like public final static class Math (oops that is in Java). IOWs you have a mix of first and second class citizens in the language. This is why it's messed up. To continue down that path is to mess it up even more. Why not back trace and work to make the second class citizens first class one?

sjasja
Offline
Joined: 2004-08-15
Points: 0

> Why not back trace and work to make the second
> class citizens first class one?

There already are a number of "pure" OO languages. If you need one, surely google will find one for you! No need to try to turn every language in the world into Eiffel.

kcpeppe
Offline
Joined: 2003-06-15
Points: 0

> > Why not back trace and work to make the second
> > class citizens first class one?
>
> There already are a number of "pure" OO languages. If
> you need one, surely google will find one for you! No
> need to try to turn every language in the world into
> Eiffel.

Why do we have to turn Java into C++ or C#?

jwenting
Offline
Joined: 2003-12-02
Points: 0

> > > Why not back trace and work to make the second
> > > class citizens first class one?
> >
> > There already are a number of "pure" OO languages.
> If
> > you need one, surely google will find one for you!
> No
> > need to try to turn every language in the world
> into
> > Eiffel.
>
> Why do we have to turn Java into C++ or C#?

Wiser words have rarely been uttered!
Answer: we don't. But there's a lot of kiddos who do seem to think that just because X (where X is any programming language of their liking) has feature Y (where Y is any feature they particularly like in language X) that Java should have that exact same feature as well and preferably using the same syntax.
More often than not the marketing types at Sun headquarters then order the language development team to find a way to include that feature because it supposedly would make Java more interesting to users of language X and thus increase its market share.

tackline
Offline
Joined: 2003-06-19
Points: 0

> More often than not the marketing types at Sun
> headquarters then order the language development team
> to find a way to include that feature because it
> supposedly would make Java more interesting to users
> of language X and thus increase its market share.

Really?

The language feature that I can think that could apply to is auto *un*boxing. Possibly the exact form of varargs. In the library there is printf. I can't think of anything else your statement could apply to. I think you made it up.

felipegaucho
Offline
Joined: 2003-06-13
Points: 0

doesn´t matter..

What we will gain with operator overloading ?

what is the difference between to write:

A + B;
A.plus(B);

just a few letters :))

mthornton
Offline
Joined: 2003-06-10
Points: 0

Try some of the more complex expressions involving complex variables that arise in electrical engineering for example. Too many additional characters (and especially parentheses) and the expression becomes unrecognisable. If you use temporary variables to spread the expression over too many lines then the amount of code you can easily see on a page/screen goes down. This again damages comprehension.

sjasja
Offline
Joined: 2004-08-15
Points: 0

> Try some of the more complex expressions involving
> complex variables that arise in electrical
> engineering for example. Too many additional
> characters (and especially parentheses) and the
> expression becomes unrecognisable.

I have worked with electricity distribution network analysis software written in C. It wasn't particularly problematic. Even if +-*/ had been overloadable the expressions wouldn't have been much like what textbooks formulas looked like. No sigma for summation, no way to draw the square root symbol on screen, no Greek letters, division by / instead of horizontal line, a*b instead of ab, ...

When you get to matrixes the overloadable operators become an even smaller part of what Real Formulas look like.

Fortunately translating the Real Formulas to computer math wasn't particularly hard. Mathematicians have been doing it from the days of FORTRAN and even before.

The ability to overload kidergarten math operators would have made a small difference. Not big enough to bother, though, IMHO. Especially given the problems C++ has shown. Advantages vs disadvantages.

johnm
Offline
Joined: 2003-06-06
Points: 0

> The technical details of how it could be implemented
> internally are interesting but not really relevant to
> the discussion.

Of course those details are important to the discussion because they don't come for free, they will impact other features, etc.

> Operator overloading definitely should be added.
> Those who don't like it are free not to use it. There
> was a similar debate against generics when this was
> proposed.

Bah! That sort of psuedo-logic is an great example of exactly the problem with so much of the thinking around operator-overloading -- completely ignoring the real, "unintended" consequences isn't logic, it's wishful thinking. Of course the simplistic examples are seductively useful (e.g., Java's support of overloading + for strings) but the consequences even with those simplistic examples are arguable (as discussed in other messages in this thread). Trying to extend the simplistic rationalization for op-overloading to the general case, for a language like Java, is just plain nuts.

Operator overloading erodes the ability for people to be able to look at the code and understand what's going on. The history of the abuses of op-overloading is overwhelmingly clear that the resulting ambiguity leads to ridiculous amounts of confusion and bugs.

Even in the very best cases (i.e., complex math) the increased density of expression costs a lot in terms of collateral damage when implemented as part of generalized op-overloading in a general purpose programming language like Java (one need look no further than the festering cesspool that is op-overloading in C++). [The analogy here is the same as how logging is the only easy, obviously useful example of AOP. :-)] It would be much better (easier, safer, etc.) to just bake in the op-overloading support for a slew of math stuff (BigInteger, BigDecimal, vector/matrix math, etc.) than it would be to add the general op-overloading capabilities. At least that way, the potential confusion over what's going on is constrained.

Java, whether we like it or not, has already been framed along certain lines. That is, the design of the language "thinks" a certain way and that matters to everyone who uses it. Rather than trying to constantly morph it with everybody's pet features, if you really have a problem that would benefit so greatly from that feature, why don't you create a language that expresses exactly what you want? There are plenty of examples that you can start with that even target the JVM so your little language (aka "domain specific language") would be completely interoperable with your Java code.

mthornton
Offline
Joined: 2003-06-10
Points: 0

> Operator overloading erodes the ability for people to
> be able to look at the code and understand what's
> going on. The history of the abuses of op-overloading
> is overwhelmingly clear that the resulting ambiguity
> leads to ridiculous amounts of confusion and bugs.

If one were to discount C++ as an aberation are there any other examples of serious abuse? Mathematicians, after all, have been overloading operators to reasonable effect for quite a while.

hlovatt
Offline
Joined: 2003-11-17
Points: 0

> If one were to discount C++ as an aberation are there
> any other examples of serious abuse? Mathematicians,
> after all, have been overloading operators to
> reasonable effect for quite a while.

Haskell - in Haskell you can have any sequence of symbols and use them infix so you get stuff like:
[code]
addA :: Arrow a => a b Int -> a b Int -> a b Int
addA f g = proc x -> do
y <- f -< x
z <- g -< x
returnA -< y + z

addA f g = arr (\ x -> (x, x) >>>
first f >>> arr (\ (y, x) -> (x, y)) >>>
first g >>> arr (\ (z, y) -> y + z))

addA f g = f &&& g >>> arr (\ (y, z) -> y + z)
[/code]
The first line above defines the types of the inputs and outputs to a function called addA. The next three sections are all different ways defining addA. addA takes two functions and a value as its input, applies both functions to the value and sums the results from the functions. The first definition is probably the clearest, f and g are the functions and x is the value. But the first definition is cheating because it also has some syntatic sugar in it as well as operators.

sjasja
Offline
Joined: 2004-08-15
Points: 0

> Sure, an idiot might use the * operator to add
> instead of multiply, but wouldn't such an idiot
> create a function called "multiply(X)" in such
> circumstances? Couldn't such an idiot create a
> function called "equals" to alter the contents
> of an object?

That doesn't seem to be happening in reality though. Programmers do use overloading for cutesy tricks; they do not seem to use random names to perform unrelated operations. Theory vs reality.

What does happen in reality is people overloading << to perform output. + to insert an object to a collection or a window to a frame. / to concatenate a directory and a file name.

> Operator overloading greatly increases readability.

Experience with C++ shows it is more often used to decrease readability.

> try to read through a long line of .multiply(X).minus(Y).divide(Z)

With experience from sin(), sqrt(), etc in mathematical software I find that the use of temporary variables enhances readability of such long lines. Just like with any long list of method calls. Even when using operators I tend to break long lines of A+(B/C)*D<<(E&F-G) with temporaries when it enhances readability.

Why are some people concerned with long lines of mathematical method calls but not with long lines of .append(W).substring(X).toString(Y).charAt(Z)? Do you actually have mathematical software with such long lines? Have you tried temporary variables?

mthornton
Offline
Joined: 2003-06-10
Points: 0

There is little dispute that overloading in C++ has been grossly abused. However that is quite different to saying that "overloading never adds clarity" because in some carefully restricted cases it clearly does.

hlovatt
Offline
Joined: 2003-11-17
Points: 0

I think operator overloading is difficult to do and current approaches from other languages are lacking, that is why so many people are against it. We need a fresh approach because operators are slightly different than normal methods in that they are related to each other and in general efficiency is a concern. Let me address efficiency first, you don't want:
[code]
r = a + b + c + d
[/code]
to be:
[code]
r = a.add(b).add(c).add(d)
[/code]
because each plus needs to make a new object (think Strings here). You want:
[code]
r = a + b + c + d
[/code]
to be something like:
[code]
final SomeType temp = a.toOperableForm();
temp.setAdd(b);
temp.setAdd(c);
temp.setAdd(d);
r = temp.fromOperableForm();
[/code]
This is how String behaves, with good reason! Therefore I suggest defining:
[code]
interface AddOperator< AO extends AddOperator< AO, A >, A extends Addable< AO, A > > {
A toOperableForm(); /* makes a deep copy and can cast if required */
}

interface Addable< AO extends AddOperator< AO, A >, A extends Addable< AO, A > > {
AO fromOperableForm(); /* makes a deep copy */
void setAdd( AO t ); /* changes the value by adding an AddOperator */
void setAdd( A t ); /* changes the value by adding an Addable */
A unity(); /* returns unity (1) */
}
[/code]
Then a class that implements AddOperator can be used with operators +, +=, ++ (pre), and ++ (post) by transforming the code as shown above for +. String would therefore implement AddOperator and StringBuilder Addable. Some classes may implement both AddOperator and Addable.

Note how the user implements setAdd and unity; but all the operators +, +=, ++ (pre), and ++ (post) are defined in terms of just setAdd and unity, thus giving consistency between operations. This is the second problem with operator overloading addressed, i.e. when temp = a; temp + b != a += b

Similarly the interfaces:
[code]
interface ArithmeticOperators< AO extends ArithmeticOperators< AO, A >, A extends Arithmeticable< AO, A > > extends AddOperator< AO, A > {
/* empty */
}
interface Arithmeticable< AO extends ArithmeticOperators< AO, A >, A extends Arithmeticable< AO, A > > extends Addable< AO, A > {
void setDivide( AO t );
void setMultiple( AO t );
void setSubtract( AO t );
void setDivide( A t );
void setMultiple( A t );
void setSubtract( A t );
}
[/code]
And a class that implemented ArithmeticOperators can not only be used with + operators, like AddOperator above, but also with /, *, and - as well as +, i.e. /=, *=, -=, etc.

Comparing is simpler than arithmetic because an intermediate class isn't needed because compare doesn't change any values:
[code]
public interface CompareOperators< T extends Comparable > extends Comparable< T >{ /* compatible with old code because it extends Comparable */
/* empty */
}
[/code]
Would allow <, >, !=, and == for a class that implemented CompareOperators. Currently, if you are implementing Comparable you shouldn't use == and equals should call compareTo. This solution elevates the problem of calling ==, but the problem of people forgetting equals remains (but is lessened since most people will use ==).

jwenting
Offline
Joined: 2003-12-02
Points: 0

The usual case of course is people overloading operators to add DoodAds to DoDos and using the multiplication operator to do it.

So you get operators working on disparate datatypes and doing things that even if they were the same datatype would not be what you'd expect them to do.

Language designers are usually more sensible than our average esteemed colleagues/competitors in the marketplace.

And as there's no way to ensure at compiler level that an overloaded operator actually does a mathematically correct job there's no way to protect people from themselves and each other when using operator overloading.
As Java is designed to protect the programmer from the more common mistakes made by C++ and other language users this is a Bad Thing, as operator overloading is among the more frequently abused features of languages like C++.

hlovatt
Offline
Joined: 2003-11-17
Points: 0

@jwenting

See post immediately above yours. I think this addresses your concerns.

fuerte
Offline
Joined: 2004-11-22
Points: 0

> operator overloading never adds clarity.

Yeah right.
[code]
a = new StringBuilder(new String({'a', 'b', 'c'})).append(new String({'d', 'e'}));
[/code]
or
[code]
a = "abc" + "de";
[/code]

kcpeppe
Offline
Joined: 2003-06-15
Points: 0

> > operator overloading never adds clarity.
>
> Yeah right.
> [code]
> a = new StringBuilder(new String({'a', 'b',
> 'c'})).append(new String({'d', 'e'}));
> [/code]

edge case...

mthornton
Offline
Joined: 2003-06-10
Points: 0

String concatenation should have had an operator of its own, '$' perhaps, rather than overloading +.

kcpeppe
Offline
Joined: 2003-06-15
Points: 0

>
> You say it makes it ambiguous because your
> programming buisiness didn't need it. So simply stay
> behind and don't put your nose in this discussion. If
> it became a feature in java, just don't use.

What my business is in this forum is to add to the discussions based on my experiences and education with computer languages. Operator overloading is a artifact of having operators in the language. IMHO a better direction is to remove operators from the langauge.

That said, it is not going to happen in Java, nor would I want it to for arguments that I've made in other threads in this forum. "==" and "=" both have a clear function. They are notationally clean. If you were to confuse the meaning of "=" you will produce code that is difficult for me to read. So it doesn't matter is I use it or not because others will.

tackline
Offline
Joined: 2003-06-19
Points: 0

That's easy: don't allow overloading of ==.

Auto-unboxing does not, as far as I am aware, introduce bugs into existing pre-1.5 source.

javac probably should give a warning if you try == on Integers, Strings and similar. Particularly if there was a method boolean identityEquals(T,T) added to System.

scmikes
Offline
Joined: 2004-03-04
Points: 0

>
> Operator overloading should only be used by experts
> to create mathematical classes (like BigDecimal,
> Complex, or Matrix or whatever).
>
> Unfortunately since lots of us Java programmers where
> brain damaged by C++.. I'd have to say that I'm
> against this feature. That is, unless it is added
> with the caveat that any application programmer that
> uses it will be taken out and shot! (Mathematical
> library developers are the only ones that need it..
> but even they should be held to a high standard)

Scientific programming would be much easier in java if operator overloading was implemented. Why should you have to go to C# if you want to write clean high-level math libraries?

lucretius2
Offline
Joined: 2004-12-19
Points: 0

> Seems as if we are creating a lot of interfaces here.
> We need an interface for each coherent set of
> operators. Probably with names that most programmers
> don't understand, like DivisionRing or SkewField.
> Adding primitives into the mix is worse.

There are ways round this. We could, as you say, have a few interfaces which contain a group of operator methods. E.g. maybe all the plus() and minus() methods, including plus(T), plus(double), plus(int), etc., could go in the same interface. If you don't want to implement some of them for a particular class, make them throw UndefinedOperationException. This is the same approach used in the Collections framework of course.

A slightly more fine-grained approach would be, say, to have an Addable interface which contains plus(T) and minus(T), then a subinterface AddablePrimitive which adds plus(int), minus(int), plus(double), minus(double) etc. This helps with the common case of a class which only lets you add objects of its own type, e.g. classes representing units (SI units, cows, maybe currency, etc.).

dog
Offline
Joined: 2003-08-22
Points: 0

Operator overloading was very simple in Smalltalk.. because Smalltalk was a simple language and operators where used for mathematical things.

In C++ (STL) the whole notion was completely and utterly abused. In a misguided attempt to make syntax concise they used it for iteration and other non-intuitive purposes which made the whole thing the horrible mess it is today (thank God Java came around and saved me from it).

Operator overloading should only be used by experts to create mathematical classes (like BigDecimal, Complex, or Matrix or whatever).

Unfortunately since lots of us Java programmers where brain damaged by C++.. I'd have to say that I'm against this feature. That is, unless it is added with the caveat that any application programmer that uses it will be taken out and shot! (Mathematical library developers are the only ones that need it.. but even they should be held to a high standard)

lucretius2
Offline
Joined: 2004-12-19
Points: 0

> Operator overloading should only be used by experts
> to create mathematical classes (like BigDecimal,
> Complex, or Matrix or whatever).

Ah, this old argument again.

Would you also say that 'implementing an interface should only be used by experts'?

If not, in what way would you say that operator overloading is not simply an alternative syntax for implementing an interface? (The interface being a set of methods called '+', '-' etc., whose contracts are whatever mathematical axioms they need to behave in a roughly number-like way.)

jwenting
Offline
Joined: 2003-12-02
Points: 0

C++ style operator overloading allows pretty much any behaviour to be defined for pretty much anything...

You loose any hint of predictable behaviour that way.

scmikes
Offline
Joined: 2004-03-04
Points: 0

> C++ style operator overloading allows pretty much any
> behaviour to be defined for pretty much anything...
>
> You loose any hint of predictable behaviour that way.

Doesn't this hold true if you overload hash() or equals() in Java?

how is myObject.equals(myOtherObject) in java any less risky the myObject == myOtherObject in C++?

scmikes
Offline
Joined: 2004-03-04
Points: 0

> Please, not now, not ever. Here's the problem with
> operator overloading, and I have dealt with all these
> issues, they make code VERY easy to get VERY wrong.
>
> what does this do: (--(++j))?
> is it the same as: (++(--j))?, with most monkeys
> typing out overloaded operators, it isn't. The second
> one will often throw an exception (think iterators),
> and the first one can too.

Operator overloading follows a very well defined set of semantics. What would your code above look like without overloaded operators, and how do I learn the semantics of your naming convention.

j.preIncrement().preDecrement();
j.preDecrement().preIncrement();

>
> How about this if(null == x), does that throw a null
> pointer exception? In lots of C# code it does, so
> there's no way to avoid the exception, a real mess.
>
> I don't even dare ask about things like (x + y) * (y
> + z)

x.plus(y).times(y.plus(z))

How do I know that the function called plus actually follows the same semantics as + ?

Operator overloading defines a very clear set of semantics that can be reviewed against these semantics.

> What does that do? Does it produce the same thing as
> xy + y^2 + xz + yz? Be careful, operators have VERY
> well defined meanings, and the whole purpose of
> overloading operators is so that you can do simple
> arithmatic with them (like that above), but this
> never works out well because people screw up their
> operators, and then simple math doesn't work in any
> sane way.
>
> Please, NEVER have any more operator overloading than
> they already do.

Please allow syntax that carries a very well defined semantics that matches the domain of scientific programming.

mthornton
Offline
Joined: 2003-06-10
Points: 0

> I don't even dare ask about things like (x + y) * (y
> + z)
> What does that do? Does it produce the same thing as
> xy + y^2 + xz + yz?

Those expressions can already produce different results with double and float values!

arae
Offline
Joined: 2004-06-22
Points: 0

Java has a big problem which will always prevent op overloading. In C++, the == op is undefined by default whereas in Java, it is well defined.

This has already introduced potential bugs in autoboxing:
int a = 1001;
Integer b = a;
a < b is false, a > b is false but a == b is false.

subanark
Offline
Joined: 2004-11-26
Points: 0

Um...
but under your above logic a == b is true.
since a is an int, and b is an Integer, b is unboxed in order to perform the == operations.
That being said:
int a = 1001;
Integer b = a;
Integer c = a;
b == c is false.

arae
Offline
Joined: 2004-06-22
Points: 0

> Um...
> but under your above logic a == b is true.
> since a is an int, and b is an Integer, b is unboxed
> in order to perform the == operations.
> That being said:
> int a = 1001;
> Integer b = a;
> Integer c = a;
> b == c is false.

Which sort of proves my point. Autoboxing has already made the == op ambiguous and that will be a source of bugs, errors and reduced maintainability.

kcpeppe
Offline
Joined: 2003-06-15
Points: 0

> > Um...
> > but under your above logic a == b is true.
> > since a is an int, and b is an Integer, b is
> unboxed
> > in order to perform the == operations.
> > That being said:
> > int a = 1001;
> > Integer b = a;
> > Integer c = a;
> > b == c is false.
>
> Which sort of proves my point. Autoboxing has already
> made the == op ambiguous and that will be a source of
> bugs, errors and reduced maintainability.

I'm no fan of Autoboxing but in this case it works as it should or as best it can. Don't forget there is a difference between deep and shallow equality. All this example is doing is pointing that out.

ramimahdi
Offline
Joined: 2004-05-29
Points: 0

if it makes your code ambiguous then just don't use it. Leave it to the others who need it.

Many people are doing applications concerned with calculations. So have operator overloading will provide great clarity to their programs.

You say it makes it ambiguous because your programming buisiness didn't need it. So simply stay behind and don't put your nose in this discussion. If it became a feature in java, just don't use.

jwenting
Offline
Joined: 2003-12-02
Points: 0

operator overloading never adds clarity. All it ever does is make code harder to understand by enabling people to write operators that have no relation at all with the mathematical representation of what that operator is normally expected to do.

mthornton
Offline
Joined: 2003-06-10
Points: 0

> operator overloading never adds clarity.

Should we be using separate operators for integers and floating point? If operator overloading makes sense for these types, then it should also be appropriate for complex numbers.
I would happily agree that overloading should be restricted to the basic mathematical operations.

mthornton
Offline
Joined: 2003-06-10
Points: 0

While user defined operator overloading is unlikely, I think there is a reasonable case for adding a couple of extra classes (Complex with float and double forms), for which the appropriate operators were overloaded.

celticminstrel
Offline
Joined: 2009-01-09
Points: 0

Operator overloading is probably the one feature I really miss most in Java. I would definitely like to see it added to the language. The question is, how?

First, it seems to me that the majority of people bashing operator overloading cite "it can be abused" as a reason. This is not really a good reason not to include the feature in the language – as others have said, [i]any[/i] feature can be abused.

Second, there are some unfortunate problems with adding operator overloading to the language. The main one is the == operator (and by extension the != operator). Both of these operators are already defined for all types. While it would be nice to be able to overload == on, say, complex numbers so that it checks for equality (rather than reference equality), to do so would result in backwards compatibility issues. And if == and != cannot be overloaded, it would be inconsistent to enable overloading of the other comparison operators (< <= > >=). This would not be an issue if Java had chosen to use a different pair of operators for reference comparison (say, === and !==), but it seems too late to change that.

Another operator that would be problematic when overloading is array indexing. The fact is, this is used for two distinct operations – retrieving an element, and setting an element. In C++, this is not a problem, because it returns a reference, which can then become the left operand of the assignment operator; but in Java, this is not possible. However, you could probably define two separate operator methods to do each task.

Some operators have the quirk of not evaluating all their operands. These are the && operator, the || operator, and the ?: conditional operator. There's no real need to overload the conditional operator, and even C++ does not allow that, so no problem there. But it could be useful to overload the other two. However, if it were permitted then the unevaluated operands idea would not be able to be applied. In Java there is a possible solution to this problem which (as far as I know) does not exist in C++: the & and | operators. These have the exact same effect, but without the special treatment, so one possibility would involve overloading the & and | operators and then having the && and || operators be somehow defined in terms of them.

Some people have mentioned potential problems with overloading the assignment operators and the ++ and -- operators. I think this could be done automatically by automatically interpreting the expression "a += b" as "a = a + b" or "i++" as "i = i + 1".

So, basically I would be content with being able to overload only the following operators directly:
binary + - * / % & | ^ << >> >>>
unary - ! ~ (and maybe + if it exists)
and then defining some way of deriving the assignment and ++/-- operators from these.

I think this would actually prevent some of the things that I have noticed a few people bashing, such as the use of ++ for iterators.

One other thing I'd like to mention: one or two people suggested a mechanism to enforce the commutativity, associativity, and other intrinsic properties of the operators. However, it seems to me that doing so would actually make it useless in many of the areas where it is most useful... hence defeating the purpose of adding it in the first place.

Now. I know many people don't like operator overloading, but I am going to go over some ways in which it could be defined.

(1)

First, and most obvious, is the C++ method. Here the operators are declared with names of the form "operator +" or "operator %" and they must have very specific parameter counts. Discounting C++ global operators since that's a relic of its functional programming idiom, it shows that binary operators always take one argument and unary operators always take no arguments (with two or four exceptions). If you were to go the C++ way, operator overloading would basically allow you to write either:

a = (b * c) + (b / c)

or

a = b.operator*(c).operator+(b.operator/(c))

Frankly, that's probably not the ideal way to do it.

(2)

Okay, now let's consider the Python method of operator overloading, The general idea here is that certain method names are interpreted as overloaded operators. Python also introduces potential ambiguity for an expression "a + b": it could be interpreted either as a.__add(b) or b.__radd(a), depending on whether the former were defined. This is probably better than the C++ method, but still lacks something since names beginning with double underscores are rather ugly. But it would allow you to write

a = (b * c) + (b / c)

to mean

a = b.__mult(c).__add(b.__div(c))

That's much cleaner than the C++ version, but still not quite perfect.

(3)

Reading through this thread I found what I currently believe to be a better solution: interfaces. Yes, it would require defining a lot of interfaces (at least 10), but is that truly a problem? Notice how this is similar to Python's operator overloading: simply define a method with a specific name and signature! (Except that, unlike in Python, you also have to implement the interface.)

Here's one possible way to handle it. If you think about it, you'll notice that some of the built-in operators fall into distinct sets: {add, subtract, negate} and {multiply, divide, modulus}, for example. So define an interface for those common sets, but also define a separate interface for each individual operator (since not all contexts will require the whole set, especially in the case of multiplication).

Example interfaces:
interface Addable {
Object add(T other);
}

interface Negatable {
Object neg();
}

interface Subtractable {
Object diff(T other);
}

Then let a class implementing Addable use the + operator. The compiler will translate the expression "a + b" where a is an Addable type to "a.add(b)". Notice that if you dislike operator overloading that much, you can simply use the named method rather than the operator. Similarly, a class implementing Negatable can use the unary - operator, and a class implementing Subtractable can use the binary - operator. However, don't let these classes use ++ or --, because they require a concept of "unity" which is lacking in the interfaces (ie what is the smallest possible unit?). It could however allow the class to use the += and -= operators.

It may seem strange to you that I've listed the return types as Object. Perhaps that was a good choice, perhaps not, but I'll explain why I did it. By making the return type Object, you can use covariant return types and are not forced to return the same type that is passed to the method. You could therefore choose between returning the type of the left operand or returning the type of the right operand. Perhaps it would be better to make the return type T. I'm not really sure. Or you could define separate interfaces for the symmetric and asymmetric forms, though that seems overly complicated to me.

Now. What about an interface that allows ++ and --? Simple. Consider the following interface:
interface AddSubtractable // needs a better name, I think
extends Addable, Subtractable, Negatable {
T unity(); // returns the equivalent of 1
T additive_identity() // could use a shorter name; returns the additive identity (ie 0 equivalent)
}
Now the expression "a++" can be interpreted as "a += a.unity()" which in term is interpreted as "a = a + a.unity()". There is a minor oddity here in that the unity and additive_identity methods should really be static, but I feel that's a minor thing. Alternatively, a separate interface "Incrementable" could define unity() while the above interface only defines additive_identity().

Similarly for multiplication:
interface MultDivable // again, bad choice of name
extends Multipliable, Dividable, Modulable {
T mult_id(); // return multiplicative identity (the equivalent of 1)
}

Any thoughts?

One more thing: the original suggestion involved a "function" keyword to indicate a lack of side-effects. I don't like the choice of keyword, but I think the concept is a good idea. And how to enforce it, someone asked? Simply forbid a method qualified with the keyword from invoking a method not qualified with the keyword. Also forbid the use of assignment operators or something.

tfoster
Offline
Joined: 2008-01-31
Points: 0

Here are 2 useful sudo code examples for operator overloading that not only wouldn't change the logical meaning of the operator, but would create a more logical syntactic flow.

Array Style Indexing:
Example class:
pubilc class DynamicStringArray{
private String[] _Values;
public String operator [int index]{
// If instance is left-hand variable, value is set to right-hand variable or null if instance is the right-hand variable.
if(value != null){
if(index < _Values.getLength()){
//Perform resize functionality
}
Values[index] = value;
}
return _Values[index];
}
DynamicObjectArray(){...}
Add(String value){...}
Remove(int index){...}
}

Usage:
DynamicObjectArray doa = new DynamicObjectArray();
doa.Add(“test0”);
doa.Add(“test1”);
doa.Add(“test2”);
doa.Remove(2);
doa[1] = “new test1 value”;
String value = doa[0];

Equivalent values, different instances
Example class:
public class Location{
public int X;
public int Y;
Location(int x, int y){
X = x;
Y = y;
}
public override operator =={
// value is set to right-hand variable
return Equivalent(value);
}
private boolean Equivalent(Location value){
if(this.X == value.X && this.Y == value.Y){
return true;
} else {
return false;
}
}
}
Usage:
Location location1 = new Location(1, 5);
Location location2 = new Location(1, 5);
Location location3 = new Location(5, 7);
if(location1 == location2){
// would be true
}
if(location2 == location3){
//would be false
}

It seems that the only argument against operator overloading is potential for misuse.

That same argument could be used against any element of programming.

Crippling your language doesn't make bad programmers better, it just results in good programmers being forced to implement kludged workarounds. Which in turn causes the exact opposite of the intended outcome.

tfoster
Offline
Joined: 2008-01-31
Points: 0

Sorry, the message body is getting truncated so I'll try it a different way.

2 extremely useful examples of operator overriding would be "Same value, different instance equivalently comparisons." overriding == and "Dynamic array and text indexed array functionality" overriding [].

It seems that the only argument against operator overloading is potential for misuse.

That same argument could be used against any element of programming.

Crippling your language doesn't make bad programmers better, it just results in good programmers being forced to implement kludged work arounds. Which in turn causes the exact opposite of the intended outcome.

tarbo
Offline
Joined: 2006-12-18
Points: 0

It's not that it has the potential of falling into "wrong hands" so much as having a very limited amount of right hands to fall into.

Java was never intended to be the be-all, end-all language of the whateverth century. It was designed to be a simple, predictable, cross-platform language. If I recall correctly, operator overloading was deliberately left out of the language specification, along with pointers, [i]void[/i] variables, multiple inheritance, and some other things.

I like pointers. I like operator overloading. I like multiple inheritance. (Heck, I like assembler.) And if I need them, I use C or C++. But often, in my case, I find that the necessary use of these features is a by-product of my code being more complicated than it should be.

The truth is that, despite the many advantages that operator overloading has, it remains an advanced tool for advanced users. And if I may paraphrase an article on IBM's Developer Networks: advanced users use the simplest tools possible until they're convinced the simple tools are inadequate.

Peace out,
Jonathan

tfoster
Offline
Joined: 2008-01-31
Points: 0

> It's not that it has the potential of falling into
> "wrong hands" so much as having a very limited amount
> of right hands to fall into.

That's not true, the examples that I provided previously would be useful in many scenarios. How often do you use dynamically sizable arrays or associative arrays?

> Java was never intended to be the be-all, end-all
> language of the whateverth century. It was designed
> to be a simple, predictable, cross-platform language.
> If I recall correctly, operator overloading was
> deliberately left out of the language specification,
> along with pointers, [i]void[/i] variables, multiple
> inheritance, and some other things.

> I like pointers. I like operator overloading. I
> like multiple inheritance. (Heck, I like assembler.)
> And if I need them, I use C or C++. But often, in
> my case, I find that the necessary use of these
> features is a by-product of my code being more
> complicated than it should be.

I think that you've grouped many tools as being “deliberately left out” without fully considering the repercussions of each functionality. There are very good reasons for some or all of these functionalities to be excluded depending on the implemention of the JRE garbage collection.

If you'd like to discuss the pros and cons of “pointers, [i]void[/i] variables, multiple inheritance, and some other things.” feel free to link me to the threads that you'd like to discuss them in; but I don't think that it's productive to argue all of these tool in this thread.

> The truth is that, despite the many advantages that
> operator overloading has, it remains an advanced tool
> for advanced users.

Operator overloading might be an advanced tool for advanced users, but the result of advanced users wielding this functionality would benefit all users.

The lack of operator overloading has created syntactical inconsistencies between indexing static, dynamic and associative arrays, comparing objects and object values and several other very important widely used functionalities.

If you don't know how to use operator overloading, you don't have to; if you do you'll be happy it's there.

And if I may paraphrase an
> article on IBM's Developer Networks: advanced users
> use the simplest tools possible until they're
> convinced the simple tools are inadequate.

The problem with using this quote as a excuse for inadequacies of the language is that there are very different use cases for a byte-code as opposed to a compiled language so to say that if Java isn't powerful enough we should use C or C++ doesn't really apply.

> Peace out,
> Jonathan

ramimahdi
Offline
Joined: 2004-05-29
Points: 0

I am sick of the complains againist operator overloading because I guess none of you guys ever know how to exploit it or make big benefits from it.

I guess I have a solution for the operators priority problem.
one of you was saying the following is ambigeous

A^B*C+D

because the compalier most likely wont perform the the operations in the order that the programmer expect and hense leads to serious error.

thats make alot of sense

however if the compiler force any overloaded operater to be solly inclosed by paranthesis (one to one) then the programmer will have more info about what he is doing like the following

(((A+B)*(B-C))^D)
the execution will start from inner most parenthesis and left to right:
1-(B-C)
2-(A+B)
3-(*)
4- and finally the (^)

I guess this makes alot of clarity between the compiler and the programmer and the programmer must be able to understand this. Unless he is stupid programmer which the case we should not care about.

hopefully that will make sense

mklemm
Offline
Joined: 2005-03-29
Points: 0

NO to operator overloading, unless the associativeness, distributiveness, or commutativeness of the operators are enforced either by the syntactical construct used for operator overloading, or by compile-time internal checks.
This will, however be hard, since you never really know what types the operator will be applied to exactly when implementing a library. Polymorphism, implicit type conversions, and things like autoboxing etc. make it even harder to predict the results of an expression containing overloaded operators. Add generics, and the situation becomes completely weird...

insac
Offline
Joined: 2003-06-29
Points: 0

Why don't we make a poll proposal?

Do you think "operator overloading" would be a welcome feature in Java language?

a) NO!! I want to read my coworkers code and know what it does
b) YES!! Give us the freedom to use operation overload in our classes
c) YES.. but only on Number subclasses for the natural operation (+ - * /)
d) YES.. but only on java.* javax.* classes and their
addition should be approved by Sun

(Did I forget anything?)

Personally, I think that (a) will win..
I'm more on the (c)/(d) league but I'm curios to see if in the YES league we're more on (b),(c) or (d)

Last time I talked with a friend of mine about Operator Overloading, he said (and he was serious):
Yes.. Why can't I write String s='a'*10; to say "aaaaaaaaaa"

That scared me :-)

mthornton
Offline
Joined: 2003-06-10
Points: 0

The fact that the actual value of the expression 'a'*10 is 970 rather unfortunate. Justified I guess by the C/C++ inheritance. I tend to feel that treating char as 'unsigned short' with the full complement of math operators was not a good idea.

fuerte
Offline
Joined: 2004-11-22
Points: 0

> The fact that the actual value of the expression
> 'a'*10 is 970 rather unfortunate. Justified I guess
> by the C/C++ inheritance. I tend to feel that
> treating char as 'unsigned short' with the full
> complement of math operators was not a good idea.

Hehe, good point. So overloading * here would be good in fact. Maybe it could be overloaded to result in compiler error???

And think about "a" + 10, it is a valid Java expression, using built-in operator overloading, resulting in "a10".

jwenting
Offline
Joined: 2003-12-02
Points: 0

>
> And think about "a" + 10, it is a valid Java
> expression, using built-in operator overloading,
> resulting in "a10".

That's not operator overloading, it's an unfortunate case of 2 operators using the same symbol.

Operator overloading would have you type something like:
[code]
class Orange {}
class Apple {}
class Banana {}
...
Orange orange = new Orange();
Apple apple = new Apple();
Banana banana = apple^orange + orange - apple;

rcasha
Offline
Joined: 2003-12-08
Points: 0

The technical details of how it could be implemented internally are interesting but not really relevant to the discussion.

Operator overloading definitely should be added. Those who don't like it are free not to use it. There was a similar debate against generics when this was proposed.

Most of the arguments against operator overloading are flawed - in most cases the exact same arguments would apply equally to functions. Sure, an idiot might use the * operator to add instead of multiply, but wouldn't such an idiot create a function called "multiply(X)" in such circumstances? Couldn't such an idiot create a function called "equals" to alter the contents of an object? If we're going to withhold functionality from Java just because there are idiots out there then might as well return to pencil and paper.

Operator overloading greatly increases readability. If used improperly it can have as detrimental an effect as using any other language feature improperly. If I have a class called "Money" which combines a currency with an amount, I'd much rather have an operator+ which adds two instances, throwing an exception if they don't have the same currency, or multiplies an instance with a primitive number, than try to read through a long line of .multiply(X).minus(Y).divide(Z)... The reason it improves readability is that some objects are logically associated with adding, subtraction and so on. I can add physical money, so why not an object that represents it?

jwenting
Offline
Joined: 2003-12-02
Points: 0

No, you're NOT free not to use it.
90% of programming consists of the maintenance and use of code created by others, and if those others abuse it you're stuck with having to maintain their code.

Generics are open to abuse, but not by far to the extent that operator overloading is.

And no, limiting OO to just a few specific cases won't help. That will just open the floodgates to people screaming bloody murder that it's not allowed for their specific pet case and demanding it is expanded again and again in further releases until it is as generic as in C++.
There would still be no checks and ballances to make sure it can't be abused (and if those existed people would complain about that) as the compiler can't possibly know whether something is mathematically correct for complex objects (and for simple cases involving things like Integer and Double it's effectively already implemented through autoboxing).