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?
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.
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.
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;
Related
I am creating a simple wrapper class for numbers. Simply put, I want it to display the value 42 verses 42.0; however, it should display the value 1.6180338 as that number. Simply enough.
Code
private double number;
...
#Override
public String toString() {
return String.valueOf(
number == longValue()
? longValue()
: number );
}
...
#Override
public long longValue() {
return (long) number;
}
Issue
The problem is that the value of 42.0 is always displayed Not the correct 42 value in the toString(...) method
My Thoughts
Although the String.valueOf(...) method has a lot of overloaded methods to display the correct primitive values as strings, there is ambiguity in which overloaded method to use. It can use String.valueOf(double) or String.valueOf(long). This is because of the ternary operator statement and resulting result type.
I thought that the compiler would be able to discern the long type and call the appropriate String.valueOf(long) method. That appears to not be the case; instead, the JVM will choose at compile time the safest, yet most-confined overloaded method. In this case, that is String.valueOf(double) because it can safely convert a long to a double.
Question
I know this isn't possible in Java right now, but is something like this available in other languages currently? And is there some kind of definition that explains this method, and can you explain it in more detail?
I mean a definition like Covariance or Contra-variance. Note: I realize that the definition is not one of those two :)
As Java is statically typed language, the result of the ternary operator must have an explicit type, defined during the compilation, so the compilator can continue handling the outer expression. As the both branches of ternary are numbers, they are promoted to the more precise type as described in JLS 15.25 and 5.6.2. You can work-around this casting the arguments to the object:
return String.valueOf(
number == longValue()
? (Object)longValue()
: (Object)number );
This way you will box the numbers and use String.valueOf(Object) which works nice for both branches.
Is there an easy way to decide the resulting Java Class of a Java mathematical expression? For example, I can calculate the resulting class of something like String + double but is there something out there give the resulting class of any valid expression of mixed classes at runtime?
Background: I need this as I am using Java reflection to call methods with arguments at runtime. The arguments have been parsed from text into Expression objects where Expression is my class for handling expressions. An Expression can be made up of other Expressions. So for instance I may be parsing code like:
double c = 2.2;
double d = 3.3;
long e = 4;
int f = 1000;
double a = 0;
double b = 0;
MyObject object = new MyObject();
object.getSomething(a, b, (c+d+e)/f);
I know the Classes of a and b because they are defined variables but the Class of third argument needs to be calculated before I can do something like:
Method method = MyObject.class.getMethod("getSomething", double.class, double.class, ????);
In first place, you can't know the classes of a and b because a and b are not objects. They are local variables of the primitive type double. In java you have two basic kind of types: primitive types (boolean, byte, char, short, int, long, float, double, and maybe void) and class types. However, there is also a mechanism called autoboxing (and autounboxing) that automatically converts when necessary between primitive types and their corresponding "primitive wrapper classes" (Boolean, Byte, Character, Short, Integer, Long, Float, and Double). You can use this automatic conversion to determine the type of an expression. Example:
byte a= 10 ;
float b= 16.3 ;
int c= 34 ;
Object o= a * b + c ;
o.getClass(); // Should be Double or one of the primitive wrapper classes in the general case
// You can easily convert this to double.class through an if/elseif sequence
// or a Map.
A note of attention: When one mixes variables (and/or also parameters and/or return values) of primitive types and wrappers classes, it's very easy to lose track of types. In particular, the Java reflection API works mostly if not exclusively with wrapper classes. This means, for example, that method invoke supports parameters of class types only and thanks to autoboxing Java will convert any primitive type into a wrapper object, even if the target method really expects the primitive (in which case there will be an internal conversion back to the primitive type immediately before the reflective call). As a good experiment, try turning autoboxing/unboxing off if your compiler or IDE supports it. If not this, configure them to produce warnings on autoboxing/unboxing.
Now, if your numeric values are represented in a polymorphic way (as String, Object, or similar), then you will need to define your own rules for the resulting type of the operations (or model them after the Java language itself) and implement them accordingly. This is because Java autoboxing/unboxing is a static mechanism.
I agree with Mario Rossi's answer.
In addition, even if you were using reference expressions, you cannot in general deduce the types of the formal arguments from the types of the actual arguments on a sample call. Consider this program:
import java.lang.reflect.Method;
class Test {
public static void main(String[] args) throws NoSuchMethodException, SecurityException {
double a = 3.0;
new Test().myMethod(a);
Method method = Test.class.getMethod("myMethod", Double.class);
System.out.println(method);
}
// public void myMethod(Double d) {
// System.out.println("Double version");
// }
public void myMethod(Number d){
System.out.println("Number version");
}
}
As presented, it fails with a NoSuchMethodException, because I'm looking for a Double argument and the only method expects a Number. If I uncomment the first myMethod declaration, the getMethod call succeeds.
This answer is based on the assumption that the objective is close to full Java code interpretation.
The information about expression types is provided, directly or by reference, in the Java Language Specification, Chapter 15. Expressions. The actual number of rules that need to be implemented is smaller than it might appear, because many groups of expression forms share the same conversion rules. For example, as already mentioned in a comment on the question, binary operators with numeric operands, including operands that can be unboxed to numeric, generally use binary numeric promotion.
I have looked, unsuccessfully, for short cuts for finding the right Method object for a given call. You may need to actually go through the steps described in 15.12. Method Invocation Expressions. If so, you can use the getMethods methods instead of getMethod and apply the rules to the array of Method references.
int i = 10;
i++; // it ok primitive value can use ++.
Integer integer = 10;
integer++; // how it can use ++
MyClass myClass = new MyClass();
myClass++; // then why myclass can't use ++.
C++ has the ability to overload operators. The Java language considers this to be open to too much abuse (overloaded operators can be obfuscating) so it was never incorporated into Java.
Therefore, you can't write myClass++ as the syntax is not available to specify that operation.
But ++ does work on a selection of non-primitives. The mechanism exploited is called autoboxing. (Essentially the underlying plain-old-data type is extracted from the boxed type, incremented then re-boxed to the original reference type).
Somewhat related to this is the ability to apply += and + to java.lang.String instances. Simply put, this is a special case. Although fully aware of the risk of downvotes I regard this as one of the worst kludges in Java, particularly += which will create a new instance of a string (as strings themselves are immutable), and many Java programmers will be unaware of the effect this has on memory.
It is because of Java's autoboxing feature which is added in Java 1.5
The compiler will convert the statment as follow
Integer integer = 10;
integer.iniValue++;
You can try to add the compiler flag "javac -source 1.4" and it will return an error
From the Link provided in a comment by Konstantin V. Salikhov,
Integer has a defined method to return an int, which then has the ++ operator defined.
MyClass has no ++ operator, hence myClass++; is invalid
The method in question goes like:
Integer myInteger = 10;
myInteger.intValue++;
Autoboxing is the automatic conversion that the Java compiler makes between the primitive types and their corresponding object wrapper classes.
Operator overloading in Java has a description (as to it being not allowed) at Operator overloading in Java
Please can you tell me if it is possible to overload operators in Java? If it is used anywhere in Java could you please tell me about it.
No, Java doesn't support user-defined operator overloading. The only aspect of Java which comes close to "custom" operator overloading is the handling of + for strings, which either results in compile-time concatenation of constants or execution-time concatenation using StringBuilder/StringBuffer. You can't define your own operators which act in the same way though.
For a Java-like (and JVM-based) language which does support operator overloading, you could look at Kotlin or Groovy. Alternatively, you might find luck with a Java compiler plugin solution.
Operator overloading is used in Java for the concatenation of the String type:
String concat = "one" + "two";
However, you cannot define your own operator overloads.
In addition to all the people pointing out that + is overloaded for Strings, - is also overloaded for both floating point and integer operations, as are * and /.
[edit]
% is also overloaded for floating point, which can be a bit of a surprise for those with a C or C++ background.
Java does not allow operator overloading. The preferred approach is to define a method on your class to perform the action: a.add(b) instead of a + b. You can see a summary of the other bits Java left out from C like languages here: Features Removed from C and C++
As many others have answered: Java doesn't support user-defined operator overloading.
Maybe this is off-topic, but I want to comment on some things I read in some answers.
About readability.
Compare:
c = a + b
c = a.add(b)
Look again!
Which one is more readable?
A programming language that allows the creation of user-defined types, should allow them to act in the same way as the built-in types (or primitive types).
So Java breaks a fundamental principle of Generic Programming:
We should be able to interchange objects of built-in types with objects of user-defined types.
(You may be wondering: "Did he say 'objects of built-in'?". Yes, see here.)
About String concatenation:
Mathematicians use the symbol + for commutative operations on sets.
So we can be sure that a + b = b + a.
String concatenation (in most programming languages) doesn't respect this common mathematical notation.
a := "hello";
b := "world";
c := (a + b = b + a);
or in Java:
String a = "hello";
String b = "world";
boolean c = (a + b).equals(b + a);
Extra:
Notice how in Java equality and identity are confused.
The == (equality) symbol means:
a. Equality for primitive types.
b. Identity-check for user-defined types, therefore, we are forced to use the function equals() for equality.
But... What has this to do with operator overloading?
If the language allows the operator overloading the user could give the proper meaning to the equality operator.
You can't do this yourself since Java doesn't permit operator overloading.
With one exception, however. + and += are overloaded for String objects.
One can try Java Operator Overloading. It has its own limitations, but it worth trying if you really want to use operator overloading.
Just use Xtend along with your Java code. It supports Operator Overloading:
package com.example;
#SuppressWarnings("all")
public class Test {
protected int wrapped;
public Test(final int value) {
this.wrapped = value;
}
public int operator_plus(final Test e2) {
return (this.wrapped + e2.wrapped);
}
}
package com.example
class Test2 {
new() {
val t1 = new Test(3)
val t2 = new Test(5)
val t3 = t1 + t2
}
}
On the official website, there is a list of the methods to implement for each operator !
Or, you can make Java Groovy and just overload these functions to achieve what you want
//plus() => for the + operator
//multiply() => for the * operator
//leftShift() = for the << operator
// ... and so on ...
class Fish {
def leftShift(Fish fish) {
print "You just << (left shifted) some fish "
}
}
def fish = new Fish()
def fish2 = new Fish()
fish << fish2
Who doesnt want to be/use groovy? :D
No you cannot use the compiled groovy JARs in Java the same way. It still is a compiler error for Java.
Unlike C++, Java does not support user defined operator overloading. The overloading is done internally in java.
We can take +(plus) for example:
int a = 2 + 4;
string = "hello" + "world";
Here, plus adds two integer numbers and concatenates two strings. So we can say that Java supports internal operator overloading but not user defined.
Please can you tell me if it is possible to overload operators in Java? If it is used anywhere in Java could you please tell me about it.
No, Java doesn't support user-defined operator overloading. The only aspect of Java which comes close to "custom" operator overloading is the handling of + for strings, which either results in compile-time concatenation of constants or execution-time concatenation using StringBuilder/StringBuffer. You can't define your own operators which act in the same way though.
For a Java-like (and JVM-based) language which does support operator overloading, you could look at Kotlin or Groovy. Alternatively, you might find luck with a Java compiler plugin solution.
Operator overloading is used in Java for the concatenation of the String type:
String concat = "one" + "two";
However, you cannot define your own operator overloads.
In addition to all the people pointing out that + is overloaded for Strings, - is also overloaded for both floating point and integer operations, as are * and /.
[edit]
% is also overloaded for floating point, which can be a bit of a surprise for those with a C or C++ background.
Java does not allow operator overloading. The preferred approach is to define a method on your class to perform the action: a.add(b) instead of a + b. You can see a summary of the other bits Java left out from C like languages here: Features Removed from C and C++
As many others have answered: Java doesn't support user-defined operator overloading.
Maybe this is off-topic, but I want to comment on some things I read in some answers.
About readability.
Compare:
c = a + b
c = a.add(b)
Look again!
Which one is more readable?
A programming language that allows the creation of user-defined types, should allow them to act in the same way as the built-in types (or primitive types).
So Java breaks a fundamental principle of Generic Programming:
We should be able to interchange objects of built-in types with objects of user-defined types.
(You may be wondering: "Did he say 'objects of built-in'?". Yes, see here.)
About String concatenation:
Mathematicians use the symbol + for commutative operations on sets.
So we can be sure that a + b = b + a.
String concatenation (in most programming languages) doesn't respect this common mathematical notation.
a := "hello";
b := "world";
c := (a + b = b + a);
or in Java:
String a = "hello";
String b = "world";
boolean c = (a + b).equals(b + a);
Extra:
Notice how in Java equality and identity are confused.
The == (equality) symbol means:
a. Equality for primitive types.
b. Identity-check for user-defined types, therefore, we are forced to use the function equals() for equality.
But... What has this to do with operator overloading?
If the language allows the operator overloading the user could give the proper meaning to the equality operator.
You can't do this yourself since Java doesn't permit operator overloading.
With one exception, however. + and += are overloaded for String objects.
One can try Java Operator Overloading. It has its own limitations, but it worth trying if you really want to use operator overloading.
Just use Xtend along with your Java code. It supports Operator Overloading:
package com.example;
#SuppressWarnings("all")
public class Test {
protected int wrapped;
public Test(final int value) {
this.wrapped = value;
}
public int operator_plus(final Test e2) {
return (this.wrapped + e2.wrapped);
}
}
package com.example
class Test2 {
new() {
val t1 = new Test(3)
val t2 = new Test(5)
val t3 = t1 + t2
}
}
On the official website, there is a list of the methods to implement for each operator !
Or, you can make Java Groovy and just overload these functions to achieve what you want
//plus() => for the + operator
//multiply() => for the * operator
//leftShift() = for the << operator
// ... and so on ...
class Fish {
def leftShift(Fish fish) {
print "You just << (left shifted) some fish "
}
}
def fish = new Fish()
def fish2 = new Fish()
fish << fish2
Who doesnt want to be/use groovy? :D
No you cannot use the compiled groovy JARs in Java the same way. It still is a compiler error for Java.
Unlike C++, Java does not support user defined operator overloading. The overloading is done internally in java.
We can take +(plus) for example:
int a = 2 + 4;
string = "hello" + "world";
Here, plus adds two integer numbers and concatenates two strings. So we can say that Java supports internal operator overloading but not user defined.