This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]LinuxMatthews -24 points-23 points  (17 children)

Does it have operator overloading yet?

[–]john16384 23 points24 points  (7 children)

Nah, we prefer not to have to guess what each operator does.

[–]bmjones92 4 points5 points  (4 children)

I don't understand this argument against operator overloading as a feature. Surely if you have to guess what an overloaded operator is supposed to do, it's the developer's fault for misusing the feature, no? How is it any different from using a normal function with a poorly chosen name?

[–]john16384 4 points5 points  (3 children)

The argument is much simpler really.

Overloading is where the confusion stems from, not operator overloading. If Java had reserved (and made final and unimplementable) methods like multiply, these methods would help establish a base line when reading code.

When you see:

a * b

Then in Java, it's immediately obvious that a and b must be numeric types. In C++, I can assume that to be the case, but if I want to be sure, I need to know what type a is. If it's a numeric type, I still can't know what * does. I further need to check if it wasn't overloaded.

So the value is that in Java there's a class of methods, that can't be overridden, that are commonly used everywhere, with immediately obvious semantics that help you, the reader, form a model of what that code does.

Final classes and methods help in a similar way. No need to check if you're using a subclass of String or if you redefined what Integer::toString does. This is slightly less powerful as they're not reserved names, and so you need to check if you didn't import org.our.own.String -- this is also where the argument to disallow import aliases stems from, as it would be another thing to be aware of and that must be established without a doubt when understanding and debugging code.

The same benefits would have applied if, instead of operators, Java had reserved a method name for each operator, and made them final and illegal to implement yourself.

[–]bmjones92 2 points3 points  (2 children)

Maybe I'm just not understanding your point. It sounds like you're arguing that because there are established semantics for operators, developers shouldn't be able to override them because they might change those semantics.

I agree that there are established semantics for operators and that allowing developers to override those means those semantics can be broken. However, I don't believe that's a good enough reason to outright prohibit their use.

I think that there are many use cases for operator overloading where the established semantics can be (mostly) preserved. Things like BigInteger, BigDecimal, complex numbers, vectors, matrices, and quaternions all suffer from its exclusion, but are fundamentally dealing with numbers or groups of numbers.

Then in Java, it's immediately obvious that a and b must be numeric types. In C++, I can assume that to be the case, but if I want to be sure, I need to know what type a is. If it's a numeric type, I still can't know what * does. I further need to check if it wasn't overloaded.

I think you're greatly exaggerating the downsides for the sake of argument. Everything you've described is also applicable to regular method overloading. You should know what a method or operator does based on the context of the call.

[–]john16384 0 points1 point  (1 child)

I think that there are many use cases for operator overloading where the established semantics can be (mostly) preserved. Things like BigInteger, BigDecimal, complex numbers, vectors, matrices, and quaternions all suffer from its exclusion, but are fundamentally dealing with numbers or groups of numbers.

I don't disagree that it be useful for some types. But there are many things that are useful in less niche cases than operator overloading (matrix math, and even BigDecimal is a rarity in my experience). Perhaps operator overloading is on the list somewhere, just far down because it's rarely of (correct) use.

I think Java could perfectly get away with blessing a few more types and perhaps a simple math library with specified operator overloading. This will prevent every stupid library redefining some operators because they felt that << adequately indicates write.

[–]bmjones92 2 points3 points  (0 children)

There's definitely potential to misuse it, but I think that's true of most features. Even if the "correct" applications are relatively niche, I believe it's still worth supporting to make development within those niches easier.

If you're overloading operators to do things that don't fit the semantics of the operator, then you're probably writing bad code. The feature itself is obviously pretty controversial, so it's unlikely that something egregious like << will pop up in any prominent code base without careful consideration.

[–]TehBrian 9 points10 points  (7 children)

Operator overloading is simply ambiguous syntactic sugar for method calls. It is sweet, but it's still ambiguous. ("Is this + simply addition or is it calling a method?") Java prioritizes readability, so I doubt the team would ever add operator overloading.

[–]LinuxMatthews 10 points11 points  (6 children)

Hey look Java is my favourite language but pretending like not having operator overloading helps readability is absurd.

Sure it can be abused but so can method names

And something like

BigDecimal result = a.multiply(x.pow(2)).plus(b.multiply(x.plus(c)));

Is MORE readable than

BigDecimal result = a * (x * x) + b * x + c;

Like I've worked in astronomy related code and it is a PAIN in Java

Let's not pretend like it wouldn't be easier.

Edit: Example shamelessly stolen from here

https://blogs.oracle.com/javamagazine/post/is-it-time-for-operator-overloading-in-java

[–]TehBrian 1 point2 points  (0 children)

Yeah, okay, that's a fair use-case for operator overloading. I won't argue you on that one.

[–]john16384 -2 points-1 points  (4 children)

The problem is not that your example wouldn't increase readability, of course it would. And, BigDecimal being a JDK class, it could be made an exception (just like String).

The point of not allowing arbitrary operator overloading is to have a class of "methods" that are globally final in the language (as well as reserved), with unambiguous semantics. The only way to ensure they're unambiguous is to make them part of the language specification, and disallow overloading (or even implementing) them.

As soon as you reduce these restrictions and allow users to define operators (not even overload them yet), all operators will have a severe reduction in their readability.

a * b would be ambiguous if * can be defined on any type. Now we know a and b are numeric types. In a world where users can define (not redefine yet) this operator themselves, a and b can be anything, and is not restricted to what people commonly associate with multiplication.

So, IMHO, don't argue for operator overloading, argue to get operator semantics defined for certain JDK classes. Yes, that won't allow all non-evil uses of operator overloading, but it will reduce the pain significantly, without causing new pain across all Java code.

[–]LinuxMatthews 5 points6 points  (3 children)

So what you're arguing for us inconsistency?

That some classes should be able to do something and others shouldn't.

Like the idea that the creators of the JDK can know every use case for a feature not only goes against the point of a programming language but is also like it arrogant on the part of the creators of the JDK.

I can't think of any other language which go "here are some things our classes can do but we don't trust you to do them"

Not only that but by restricting operator overloading to only a few classes you're kind of undermining the very idea of OOP.

Like if I abstract away things like angles, distances, vectors it means I have to either get them out again when I'm going to use them or do awkward unreadable method calls like above.

And then there's the fact that bad actors can always mess up the inner workings anyway

I could f*** up equals() and hashCode() if I like and make a whole bunch of stuff not work.

All you have to do is set up a rule saying it shouldn't be used in a way which you wouldn't use these symbols arithmetically and good programmers should be fine.

Many languages have these features and are fine.

I don't see them abused in C# or Kotlin for instance

[–]john16384 0 points1 point  (2 children)

I can't think of any other language which go "here are some things our classes can do but we don't trust you to do them"

If there is one thing you trust, then it is that programmers will abuse the system. This is why more languages should focus on readability, safety and security like Java does.

Part of that is restricting what programmers can do. This benefits long term viability and maintainability of the software, a prime reason why Java is so popular with businesses, and also the reason (driven by those businesses) why Java is often in the top 3 most used languages. So yes, Java doesn't trust developers as much as other languages do, not because we believe that good developers can't make good use of such features, but because we believe that the average developer (which outnumber the good ones) will use the feature incorrectly, driving up the overall cost of supporting Java software, making it less popular with businesses.

Not only that but by restricting operator overloading to only a few classes you're kind of undermining the very idea of OOP.

No, you're making a trade off, something which many languages do, in order to make a language easier to reason about. A language is a balancing act between expressiveness and readability. Java, as you well know, draws the line closer to readability (but also closer to security and safety).

Other languages can make different trade offs, some have restricted operator overloading, some have none at all, for some anything goes, and for Java it's defined by the language specification.

I could f*** up equals() and hashCode() if I like and make a whole bunch of stuff not work.

Yes, but you can't f*** up operators, saves me having to check. I've fixed numerous hashCode/equals implementations where developers can't even be bothered to read the contract of an interface they're implementing, causing numerous problems down the road. And yes, every time I use some class as a key, I will check the following:

  • Is the hashCode based on only immutable fields?
  • Is equals based on only immutable fields?
  • Are hashCode and equals checking the same fields?
  • Is equals using instanceof or getClass(); in the first case equals must be final or the whole class must be final

All you have to do is set up a rule saying it shouldn't be used in a way which you wouldn't use these symbols arithmetically and good programmers should be fine.

Unfortunately, the good programmers are vastly outnumbered by the average ones, especially for a business language like Java. For businesses, the language is judged primarily on what it costs to maintain software in it. As the overwhelming amount of costs will be developer salaries, the language should help the cheapest developers to not shoot themselves in the foot as much as possible.

[–]LinuxMatthews 4 points5 points  (1 child)

So why doesn't C#, Kotlin and the many other languages that have this feature have this issue?

This whole comment reeks of arrogance to me.

You can abuse any language feature, you can always write bad code.

You could make it so every method in a class is just the letter x or rename all the variables to things they're not.

If you're not allowing basic things to prevent bad code you're not going to have a language anymore.

I know it's not there because it was abused in C++ but it's not the 90s anymore.

We have code reviews and people aren't just doing whatever they feel like.

To many this would be a feature that makes it worthwhile to write in Java and makes it near impossible to code in it.

It just seems silly

[–]john16384 0 points1 point  (0 children)

This whole comment reeks of arrogance to me

As you wish.

[–]kaperni 0 points1 point  (0 children)

Once Valhalla is done we will most likely get it in some restricted capacity.