Hacker News new | past | comments | ask | show | jobs | submit login

> These are really two separate purposes with a different interface contract.

This is a basic feature of inheritance in an object oriented language, you can take an interface that guarantees "this returns some string" and offer a more concrete guarantee "this returns the objects value as decimal" in the implementation.

> and to restrict implicit string conversion (concatenation) to classes implementing a StringConvertible interface with a corresponding separate toString method.

So anyone wanting to make their code trivially loggable now has to implement StringConvertible by copy pasting String toString(){ return toDebugString(); } into every single class they are implementing? You managed to make Java more verbose for no gain at all, please collect your AbstractAwardInstanceFactoryBuilder on your way out.






> So anyone wanting to make their code trivially loggable now has to implement StringConvertible by copy pasting String toString(){ return toDebugString(); } into every single class they are implementing?

If you actually want to output a debug representation, you’ll explicitly call toDebugString(). (And a debugger would call it by default.) This would also make the purpose explicit in the code. And you would’t accidentally output a random debug representation (like the default "@xxxxxxxx") as part of regular string concatenation/interpolation, like on a user-level message, or as a JSON value or whatever. This is why it would be wrong to have a toString() forward to toDebugString().

Currently, for most classes I have to add javadoc for the toString() method saying something like: “Returns a debug representation of this object. WARNING: The exact representation may change in future versions, do not rely on it.” For some of these classes a reliable non-debug string representation would conceivably make sense, but I chose not to have one because there is no immediate need. However, callers need to know which it is, and therefore the documentation is needed.

Conversely, whenever I want to use the toString() of a third-party class, I have to check what kind of output it generates, but unfortunately it’s often not documented. And if testing it (or looking at the source) seems to produce a stable value representation, one has no choice but to hope that it will remain stable, instead of that being part of the contract.

Furthermore, for classes with a value representation it often makes sense to have a different debug representation (for example, with safely escaped control characters or additional meta-data). In current Java, it’s safer to have those in a different, non-standard method than toString() (because users expect the latter to provide the value representation), but then there’s the inconvenience that the debug representation won’t be picked up by debuggers by default, due to the non-standard method.

This is all a symptom of the same method being used for different purposes. And a debug representation makes always sense (as evidenced by the default implementation), while a value representation only sometimes makes sense, and might be absent even when it would make sense. But you generally can’t tell from the method.

Having different methods would solve those issues. With a toDebugString() method, one wouldn’t have to document anything, because the javadoc I paraphrased above would already be contained in the Object class. And the toString() method would only be present for classes that do provide a defined value representation that makes sense on the business/domain level of the class.


> And a debugger would call it by default.

But a debugger is far from the only time you want to output a debug representation. A properly formatted log message is the most common case I deal with and one where you can generally use String manipulation freely without fear of breaking anything important.

> This would also make the purpose explicit in the code.

So you made the debug output explicit and verbose, but left toString() a mess that according to you will at least be used for "user-level" messages, JSON and "whatever", which are completely distinct use cases that have nothing in common other than that they output a string as a result. Worse, trying random string operations on a JSON output can break the JSON, so your list of example use cases for implicit string conversion already favors brittle stringly typed code.

> (for example, with safely escaped control characters or additional meta-data).

That assumes the class knows exactly how it is going to be displayed. Which only works if you have a well defined debugger interface for that. At which point you are probably better of dropping the stringly typed code and provide the debugger with a type safe interface for its output, especially since you mention "meta-data".

> This is all a symptom of the same method being used for different purposes.

And your "solution" does nothing to fix that. You might be better of killing toDebugString and toString entirely instead of turning one not so great API into two completely arbitrary and just as bad APIs and force people to roll their own. At which point people trying to output an object for anything will have to chain dozens of instanceof checks to see which kind of String representation the object supports, making the language worse to use.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: