4

Delphi is like an England Queen Guard. It does not like ambiguity and may even kill to protect the hard code. But Java is almost a street corner woman. When I use this is java:

 Button button = new Button();
 String a = "This is a " + button;

I get This is a button

But if I do that in Delphi:

 ShowMessage('This is a ' + Button1);

I get an error, because Delphi has toString() method (now) but it does not implicitly calls it. Because literal strings are not objects in OP. The correct use is:

 ShowMessage('This is a ' + Button1.toString());

Is there any way to override this behave so it works like Java?

For reference: How an object will call toString method implicitly?

Community
  • 1
  • 1
NaN
  • 8,596
  • 20
  • 79
  • 153
  • I don't think that's possible even in the last version of delphi, you can do something similar with "records" and operators, using "class operator" on "records", despite the "class" keyword, see http://docwiki.embarcadero.com/RADStudio/XE4/en/Operator_Overloading_(Delphi) for more information. –  Jun 28 '13 at 13:35
  • 9
    not sure if I should +1 or -1 you for calling Java a whore. – MK. Jun 28 '13 at 13:36
  • 1
    The default toString() implementation in Java will not give the object (variable) name, it will return something like someObjectClassname@hashcodenumber - see http://stackoverflow.com/questions/4712139 – mjn Jun 28 '13 at 13:49
  • Yes, like in Delphi, it was made so class creators create their own implementation of `toString()` to return something more substantial to the new class, like returning a date when you create a date handler class. – NaN Jun 28 '13 at 13:57
  • If it's no more adequate than creating a `GetDate()` I can't tell. Depends on the developer's will. – NaN Jun 28 '13 at 13:58
  • 1
    Note that in Java this feature is not limited to objects. Since Java's first version, string concatenation also works with primitive types. – mjn Jun 28 '13 at 13:59
  • @MK that's why everybody wants "her" ;-) – NaN Jun 28 '13 at 14:02
  • 1
    I think you may try to implement some interface or record with implicit typecasts. Then it would go like `IMyString := 'This is a '; IMyString := IMyString + Button1;` – Arioch 'The Jun 28 '13 at 14:03
  • @mjn does it ? or is it really implicit boxing and ocncatenation of objects and not of primitive types ? I bill that this whole question was made out of last Allen Bauer blog post about ARC and Delphi future directions. – Arioch 'The Jun 28 '13 at 14:04
  • @Arioch'The you mean like http://stackoverflow.com/questions/7666786/delphi-xe-casting-to-a-record-type-with-implicit-conversion ? He should at least show to us the declaration of that record he mentioned. Can you reproduce in an answer here? – NaN Jun 28 '13 at 14:08
  • @EASI like that or like recently mentioned Andreas' `IWeakPtr` hack. – Arioch 'The Jun 28 '13 at 14:12
  • damn! i meant flattered, not flattened! jeez... – Arioch 'The Jun 28 '13 at 14:13
  • The question now is: is it a good idea to insert class operators in the TObject class definition so it would work like Java? – NaN Jun 28 '13 at 14:25
  • @Arioch'The no, Autoboxing is a feature which was introduced in Java 5 (eight years later) – mjn Jun 28 '13 at 14:30
  • Cool. People I know that are Java evangelizers and Delphi crucifyiers would never accept that truth. :-P – NaN Jun 28 '13 at 14:33
  • @EASI I am confused: which thruth? – mjn Jun 28 '13 at 14:39
  • That many Java features are in Delphi even before, but developers just don't use them, because they're too unstable and hard to do maintenance. IMHO – NaN Jun 28 '13 at 14:57

3 Answers3

6

There's no way to enforce an implicit cast or method call on an object instance.

If this was a record that you controlled then you could implement an Implicit class operator that would perform a cast to string.

The issue discussed link that you refer to is simply an implementation detail of PrintStream.println(). That relies on the ability of String.valueOf() to come up with a string representation for any object which in turn relies on Object.toString(). In fact the discussion there concerning println() is unrelated to the way the + operator in Java works which is the pertinent issue in your question.

Delphi's TObject has a virtual ToString method that could be used to perform the same purpose. So it would be easy enough to use the exact same technique as PrintStream.println() in Delphi code.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
4

If you had a special function that worked like Format, you could get that behavior. I wrote a function like that several years ago, back when the built-in function didn't support Unicode. I've now updated it to support calling ToString on an object when it's passed as the argument for the %s format string. You'd call it like this:

ShowMessage(WideFormat('This is a %s', [Button1]));

I'm sorry the code hasn't really been touched in several years, so it might not work as-is in newer Delphi versions. You'll have to decide whether it's worth the effort to update that code, although it was included in Project Jedi long enough that it did get a few nominal updates to support UnicodeString and 64-bit compilation.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • Thank you. I'm afraid I can't really vouch for its quality anymore, though, since the last version of Delphi I had was Delphi 2005. Someone should update the code to account for UnicodeString as the native data type instead of just an argument type, but I'm not sure I'm the one to do it. It's all on GitHub, though, so anyone feeling so inspired can fork it or send me a pull request. – Rob Kennedy Jun 28 '13 at 16:34
  • I second @EASI the code was pleasure to read:) But wait.. your last Delphi version was Delphi 2005..does it mean you are not coding in Delphi/Pascal anymore?:( – Wodzu Jun 28 '13 at 17:28
  • I haven't used Delphi since 2007, @Wodzu (except for a few minutes last weekend helping my dad debug a hanging program in Delphi 5). I haven't used Delphi professionally since 2005. – Rob Kennedy Jun 28 '13 at 17:43
  • Not really, @David. I had a test project I used during development. Mostly just one call to the function, and I'd change the argument list for each case I wished to test. This was close to 10 years ago; I'd never heard of unit tests at the time. – Rob Kennedy Jun 28 '13 at 18:01
  • That makes porting to Unicode Delphi a little less appealing. – David Heffernan Jun 28 '13 at 18:16
2

Too bad that it works only on ARM compiler and Delphi.NET Great article by Nick Hodges in http://edn.embarcadero.com/article/34324

TMyClass = class
    class operator Add(a, b: TMyClass): TMyClass; // Addition of two operands of type TMyClass
    class operator Subtract(a, b: TMyClass): TMyclass; // Subtraction of type TMyClass
    class operator Implicit(a: Integer): TMyClass; // Implicit conversion of an Integer to type TMyClass
    class operator Implicit(a: TMyClass): Integer; // Implicit conversion of TMyClass to Integer
    class operator Explicit(a: Double): TMyClass; // Explicit conversion of a Double to TMyClass
end;

// Example implementation of Add class operator 
TMyClass.Add(a, b: TMyClass): TMyClass;
begin
  ...
end;

var
x, y: TMyClass
begin
  x := 12; // Implicit conversion from an Integer 
  y := x + x; // Calls TMyClass.Add(a, b: TMyClass): TMyClass 
  b := b + 100; // Calls TMyClass.Add(b, TMyClass.Implicit(100)) 
end;
NaN
  • 8,596
  • 20
  • 79
  • 153