Участник:VitaliyFilippov/Закладки — различия между версиями

Материал из YourcmcWiki
Перейти к: навигация, поиск
м (Декабрь 2011)
м (Ноябрь 2011)
Строка 64: Строка 64:
 
* 09 Ноябрь, 12:38:57: [http://rushim.ru/ Группа компаний «РусХим»]
 
* 09 Ноябрь, 12:38:57: [http://rushim.ru/ Группа компаний «РусХим»]
 
* 09 Ноябрь, 03:33:43: [http://stackoverflow.com/questions/77718/java-operator-overload c++ — Java operator overload — Stack Overflow]
 
* 09 Ноябрь, 03:33:43: [http://stackoverflow.com/questions/77718/java-operator-overload c++ — Java operator overload — Stack Overflow]
*: <html><p>There are a lot of posts complaining about operator overloading.</p> <p>I felt I had to clarify the «operator overloading» concepts, offering an alternative viewpoint on this concept.</p> <h1>Code obfuscating?</h1> <p>This argument is a fallacy.</p> <h2>Obfuscating is possible in all languages…</h2> <p>It is as easy to obfuscate code in C or Java through functions/methods than it is in C++ through operator overloads:</p> <pre class="default prettyprint"><code><span class="com">// C++</span><span class="pln"><br>T </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="com">// add ?</span><span class="pln"><br></span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp;T c </span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp;c</span><span class="pun">.</span><span class="pln">value </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">value </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">value </span><span class="pun">;</span><span class="pln"> </span><span class="com">// substract !!!</span><span class="pln"><br>&nbsp; &nbsp;</span><span class="kwd">return</span><span class="pln"> c </span><span class="pun">;</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br></span><span class="com">// Java</span><span class="pln"><br></span><span class="kwd">static</span><span class="pln"> T add </span><span class="pun">(</span><span class="pln">T a</span><span class="pun">,</span><span class="pln"> T b</span><span class="pun">)</span><span class="pln"> </span><span class="com">// add ?</span><span class="pln"><br></span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp;T c </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> T</span><span class="pun">()</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp;c</span><span class="pun">.</span><span class="pln">value </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">value </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">value </span><span class="pun">;</span><span class="pln"> </span><span class="com">// substract !!!</span><span class="pln"><br>&nbsp; &nbsp;</span><span class="kwd">return</span><span class="pln"> c </span><span class="pun">;</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br></span><span class="com">/* C */</span><span class="pln"><br>T add </span><span class="pun">(</span><span class="pln">T a</span><span class="pun">,</span><span class="pln"> T b</span><span class="pun">)</span><span class="pln"> </span><span class="com">/* add ? */</span><span class="pln"><br></span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp;T c </span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp;c</span><span class="pun">.</span><span class="pln">value </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">value </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">value </span><span class="pun">;</span><span class="pln"> </span><span class="com">/* substract !!! */</span><span class="pln"><br>&nbsp; &nbsp;</span><span class="kwd">return</span><span class="pln"> c </span><span class="pun">;</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br></span></code></pre> <h2>…Even in Java’s standard interfaces</h2> <p>For another example, let’s see the <code>Cloneable</code> interface in Java: <a href="http://download.oracle.com/javase/7/docs/api/java/lang/Cloneable.html" rel="nofollow">http://download.oracle.com/javase/7/docs/api/java/lang/Cloneable.html</a></p>  <p>You are supposed to clone the object implementing this interface. But you could lie. And create a different object. In fact, this interface is so weak you could return another type of object altogether, just for the fun of it:</p> <pre class="default prettyprint"><code><span class="kwd">class</span><span class="pln"> </span><span class="typ">MySincereHandShake</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><span class="typ">Cloneable</span><span class="pln"><br></span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">Object</span><span class="pln"> clone</span><span class="pun">()</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; &nbsp;</span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MyVengefulKickInYourHead</span><span class="pun">()</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="pun">}</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br></span></code></pre> <p>As the <code>Cloneable</code> interface can be abused/obfuscated, should it be banned on the same grounds C++ operator overloading are supposed to be?</p> <p>We could overload the <code>toString()</code> method of a <code>MyComplexNumber</code> class to have it return the stringified hour of the day. Should the <code>toString()</code> overloading be banned, too? We could sabotage <code>MyComplexNumber.equals</code> to have it return a random value, modify the operands… etc. etc. etc..</p> <p><b>In Java, as in C++, or whatever language, the programmer must respect a minimum of semantics when writing code. This means implementing a <code>add</code> function that adds, and <code>Cloneable</code> implementation method that clones, and a <code>++</code> operator than increments.</b></p> <h1>What’s obfuscating anyway?</h1> <p>Now that we know that code can be sabotaged even through the pristine Java methods, we can ask ourselves about the real use of operator overloading in C++?</p> <h2>Clear and natural notation: methods vs. operator overloading?</h2> <p>We’ll compare below, for different cases, the «same» code in Java and C++, to have an idea of which kind of coding style is clearer.</p> <h3>Natural comparisons:</h3> <pre class="default prettyprint"><code><span class="com">// C++ comparison for built-ins and user-defined types</span><span class="pln"><br></span><span class="kwd">bool</span><span class="pln"> &nbsp; &nbsp;isEqual &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="pun">=</span><span class="pln"> A </span><span class="pun">==</span><span class="pln"> B </span><span class="pun">;</span><span class="pln"><br></span><span class="kwd">bool</span><span class="pln"> &nbsp; &nbsp;isNotEqual &nbsp; &nbsp; &nbsp; </span><span class="pun">=</span><span class="pln"> A </span><span class="pun">!=</span><span class="pln"> B </span><span class="pun">;</span><span class="pln"><br></span><span class="kwd">bool</span><span class="pln"> &nbsp; &nbsp;isLesser &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="pun">=</span><span class="pln"> A </span><span class="pun">&lt;</span><span class="pln"> &nbsp;B </span><span class="pun">;</span><span class="pln"><br></span><span class="kwd">bool</span><span class="pln"> &nbsp; &nbsp;isLesserOrEqual &nbsp;</span><span class="pun">=</span><span class="pln"> A </span><span class="pun">&lt;=</span><span class="pln"> B </span><span class="pun">;</span><span class="pln"><br><br></span><span class="com">// Java comparison for user-defined types</span><span class="pln"><br></span><span class="kwd">boolean</span><span class="pln"> isEqual &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="pun">=</span><span class="pln"> A</span><span class="pun">.</span><span class="pln">equals</span><span class="pun">(</span><span class="pln">B</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br></span><span class="kwd">boolean</span><span class="pln"> isNotEqual &nbsp; &nbsp; &nbsp; </span><span class="pun">=</span><span class="pln"> </span><span class="pun">!</span><span class="pln"> A</span><span class="pun">.</span><span class="pln">equals</span><span class="pun">(</span><span class="pln">B</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br></span><span class="kwd">boolean</span><span class="pln"> isLesser &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="pun">=</span><span class="pln"> A</span><span class="pun">.</span><span class="pln">comparesTo</span><span class="pun">(</span><span class="pln">B</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br></span><span class="kwd">boolean</span><span class="pln"> isLesserOrEqual &nbsp;</span><span class="pun">=</span><span class="pln"> A</span><span class="pun">.</span><span class="pln">comparesTo</span><span class="pun">(</span><span class="pln">B</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br></span></code></pre> <p>Please note that A and B could be of any type in C++, as long as the operator overloads are provided. In Java, when A and B are not primitives, the code can become very confusing, even for primitive-like objects (BigInteger, etc.)…</p> <h3>Natural array/container accessors and subscripting:</h3> <pre class="default prettyprint"><code><span class="com">// C++ container accessors, more natural</span><span class="pln"><br>value &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="pun">=</span><span class="pln"> myArray</span><span class="pun">[</span><span class="lit">25</span><span class="pun">]</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// subscript operator</span><span class="pln"><br>value &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="pun">=</span><span class="pln"> myVector</span><span class="pun">[</span><span class="lit">25</span><span class="pun">]</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="com">// subscript operator</span><span class="pln"><br>value &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="pun">=</span><span class="pln"> myString</span><span class="pun">[</span><span class="lit">25</span><span class="pun">]</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="com">// subscript operator</span><span class="pln"><br>value &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="pun">=</span><span class="pln"> myMap</span><span class="pun">[</span><span class="str">«25»</span><span class="pun">]</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// subscript operator</span><span class="pln"><br>myArray</span><span class="pun">[</span><span class="lit">25</span><span class="pun">]</span><span class="pln"> &nbsp;</span><span class="pun">=</span><span class="pln"> value </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// subscript operator</span><span class="pln"><br>myVector</span><span class="pun">[</span><span class="lit">25</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> value </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// subscript operator</span><span class="pln"><br>myString</span><span class="pun">[</span><span class="lit">25</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> value </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// subscript operator</span><span class="pln"><br>myMap</span><span class="pun">[</span><span class="str">«25»</span><span class="pun">]</span><span class="pln"> &nbsp;</span><span class="pun">=</span><span class="pln"> value </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// subscript operator</span><span class="pln"><br><br></span><span class="com">// Java container accessors, each one has its special notation</span><span class="pln"><br>value &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="pun">=</span><span class="pln"> myArray</span><span class="pun">[</span><span class="lit">25</span><span class="pun">]</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// subscript operator</span><span class="pln"><br>value &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="pun">=</span><span class="pln"> myVector</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="lit">25</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp;</span><span class="com">// method get</span><span class="pln"><br>value &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="pun">=</span><span class="pln"> myString</span><span class="pun">.</span><span class="pln">charAt</span><span class="pun">(</span><span class="lit">25</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> </span><span class="com">// method charAt</span><span class="pln"><br>value &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="pun">=</span><span class="pln"> myMap</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">«25»</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; </span><span class="com">// method get</span><span class="pln"><br>myArray</span><span class="pun">[</span><span class="lit">25</span><span class="pun">]</span><span class="pln"> &nbsp;</span><span class="pun">=</span><span class="pln"> value </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// subscript operator</span><span class="pln"><br>myVector</span><span class="pun">.</span><span class="kwd">set</span><span class="pun">(</span><span class="lit">25</span><span class="pun">,</span><span class="pln"> value</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="com">// method set</span><span class="pln"><br>myMap</span><span class="pun">.</span><span class="kwd">set</span><span class="pun">(</span><span class="str">«25»</span><span class="pun">,</span><span class="pln"> value</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// method set</span><span class="pln"><br></span></code></pre> <p>In Java, we see that for each container to do the same thing (access its content through an index or identifier), we have a different way to do it, which is confusing.</p> <p>In C++, each container uses the same way to access its content, thanks to operator overload.</p> <h3>Natural advanced types manipulation</h3> <p>The examples below use a <code>Matrix</code> object, found using the first links found on Google for «<a href=»https://encrypted.google.com/search?q=Java+Matrix+object" rel="nofollow">Java Matrix object</a>" and «<a href=»https://encrypted.google.com/search?q=c%2B%2B+Matrix+object" rel="nofollow">c++ Matrix object</a>":</p> <pre class="default prettyprint"><code><span class="com">// C++ YMatrix matrix implementation on CodeProject</span><span class="pln"><br></span><span class="com">// http://www.codeproject.com/KB/architecture/ymatrix.aspx</span><span class="pln"><br></span><span class="com">// A, B, C, D, E, F are Matrix objects;</span><span class="pln"><br>E </span><span class="pun">=</span><span class="pln"> &nbsp;A </span><span class="pun">*</span><span class="pln"> </span><span class="pun">(</span><span class="pln">B </span><span class="pun">/</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>E </span><span class="pun">+=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">A </span><span class="pun">-</span><span class="pln"> B</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">(</span><span class="pln">C </span><span class="pun">+</span><span class="pln"> D</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>F </span><span class="pun">=</span><span class="pln"> &nbsp;E </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="com">// deep copy of the matrix</span><span class="pln"><br><br></span><span class="com">// Java JAMA matrix implementation (seriously…)</span><span class="pln"><br></span><span class="com">// http://math.nist.gov/javanumerics/jama/doc/</span><span class="pln"><br></span><span class="com">// A, B, C, D, E, F are Matrix objects;</span><span class="pln"><br>E </span><span class="pun">=</span><span class="pln"> A</span><span class="pun">.</span><span class="pln">times</span><span class="pun">(</span><span class="pln">B</span><span class="pun">.</span><span class="pln">times</span><span class="pun">(</span><span class="lit">2</span><span class="pun">))</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>E</span><span class="pun">.</span><span class="pln">plusEquals</span><span class="pun">(</span><span class="pln">A</span><span class="pun">.</span><span class="pln">minus</span><span class="pun">(</span><span class="pln">B</span><span class="pun">).</span><span class="pln">times</span><span class="pun">(</span><span class="pln">C</span><span class="pun">.</span><span class="pln">plus</span><span class="pun">(</span><span class="pln">D</span><span class="pun">)))</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>F </span><span class="pun">=</span><span class="pln"> E</span><span class="pun">.</span><span class="pln">copy</span><span class="pun">()</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="com">// deep copy of the matrix</span><span class="pln"><br></span></code></pre> <p>And this is not limited to matrices. The <code>BigInteger</code> and <code>BigDecimal</code> classes of Java suffer from the same confusing verbosity, whereas their equivalent in C++ are as clear as built-in types.</p> <h3>Natural iterators:</h3> <pre class="default prettyprint"><code><span class="com">// C++ Random Access iterators</span><span class="pln"><br></span><span class="pun">++</span><span class="pln">it </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="com">// move to the next item</span><span class="pln"><br></span><span class="pun">--</span><span class="pln">it </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="com">// move to the previous item</span><span class="pln"><br>it </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// move to the next 5th item (random access)</span><span class="pln"><br>value </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*</span><span class="pln">it </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// gets the value of the current item</span><span class="pln"><br></span><span class="pun">*</span><span class="pln">it </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3.1415</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="com">// sets the value 3.1415 to the current item</span><span class="pln"><br></span><span class="pun">(*</span><span class="pln">it</span><span class="pun">).</span><span class="pln">foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// call method foo() of the current item</span><span class="pln"><br><br></span><span class="com">// Java ListIterator&lt;E&gt; «bi-directional» iterators</span><span class="pln"><br>value </span><span class="pun">=</span><span class="pln"> it</span><span class="pun">.</span><span class="kwd">next</span><span class="pun">()</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; </span><span class="com">// move to the next item &amp; return the value</span><span class="pln"><br>value </span><span class="pun">=</span><span class="pln"> it</span><span class="pun">.</span><span class="pln">previous</span><span class="pun">()</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> </span><span class="com">// move to the previous item &amp; return the value</span><span class="pln"><br>it</span><span class="pun">.</span><span class="kwd">set</span><span class="pun">(</span><span class="lit">3.1415</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="com">// sets the value 3.1415 to the current item</span><span class="pln"><br></span></code></pre> <h3>Natural functors:</h3> <pre class="default prettyprint"><code><span class="com">// C++ Functors</span><span class="pln"><br>myFunctorObject</span><span class="pun">(</span><span class="str">«Hello World»</span><span class="pun">,</span><span class="pln"> </span><span class="lit">42</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br><br></span><span class="com">// Java Functors ???</span><span class="pln"><br>myFunctorObject</span><span class="pun">.</span><span class="pln">execute</span><span class="pun">(</span><span class="str">«Hello World»</span><span class="pun">,</span><span class="pln"> </span><span class="lit">42</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br></span></code></pre> <h3>Text concatenation:</h3> <pre class="default prettyprint"><code><span class="com">// C++ stream handling (with the &lt;&lt; operator)</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stringStream &nbsp; </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Hello "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">25</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">« World»</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fileStream &nbsp; &nbsp; </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Hello "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">25</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">« World»</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; outputStream &nbsp; </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Hello "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">25</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">« World»</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; networkStream &nbsp;</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Hello "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">25</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">« World»</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>anythingThatOverloadsShiftOperator </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Hello "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">25</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">« World»</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br><br></span><span class="com">// Java concatenation</span><span class="pln"><br>myStringBuffer</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="str">"Hello "</span><span class="pun">).</span><span class="pln">append</span><span class="pun">(</span><span class="lit">25</span><span class="pun">).</span><span class="pln">append</span><span class="pun">(</span><span class="str">« World»</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br></span></code></pre> <p>Ok, in Java you can use <code>MyString = "Hello " + 25 + « World» ;</code> too… But, wait a second: This is operator overloading, isn’t it? Isn’t it cheating???</p> <p>:-D</p> <h2>Generic code?</h2> <p>The same generic code modifying operands should be usable both for built-ins/primitives (which have no interfaces in Java), standard objects (which could not have the right interface), and user-defined objects.</p> <p>For example, calculating the average value of two values of arbitrary types:</p> <pre class="default prettyprint"><code><span class="com">// C++ primitive/advanced types</span><span class="pln"><br></span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln"><br>T getAverage</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> p_lhs</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> p_rhs</span><span class="pun">)</span><span class="pln"><br></span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp;</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">p_lhs </span><span class="pun">+</span><span class="pln"> p_rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br></span><span class="kwd">int</span><span class="pln"> &nbsp; &nbsp; intValue &nbsp; &nbsp; </span><span class="pun">=</span><span class="pln"> getAverage</span><span class="pun">(</span><span class="lit">25</span><span class="pun">,</span><span class="pln"> </span><span class="lit">42</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br></span><span class="kwd">double</span><span class="pln"> &nbsp;doubleValue &nbsp;</span><span class="pun">=</span><span class="pln"> getAverage</span><span class="pun">(</span><span class="lit">25.25</span><span class="pun">,</span><span class="pln"> </span><span class="lit">42.42</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>complex complexValue </span><span class="pun">=</span><span class="pln"> getAverage</span><span class="pun">(</span><span class="pln">cA</span><span class="pun">,</span><span class="pln"> cB</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> </span><span class="com">// cA, cB are complex</span><span class="pln"><br></span><span class="typ">Matrix</span><span class="pln"> &nbsp;matrixValue &nbsp;</span><span class="pun">=</span><span class="pln"> getAverage</span><span class="pun">(</span><span class="pln">mA</span><span class="pun">,</span><span class="pln"> mB</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> </span><span class="com">// mA, mB are Matrix</span><span class="pln"><br><br></span><span class="com">// Java primitive/advanced types</span><span class="pln"><br></span><span class="com">// It won’t really work in Java, even with generics. Sorry.</span><span class="pln"><br></span></code></pre> <h1>Discussing operator overloading</h1> <p>How that we saw fair comparisons between C++ code using operator overloading, and the same code in Java, we can know discuss the «operator overloading» as a concept.</p> <h2>Operator overloading existed since before computers</h2> <p><b>Even outside of computer science, there are operator overloading: For example, in mathematics, operators like <code>+</code>, <code>-</code>, <code>*</code>, etc. are overloaded.</b></p> <p>Indeed, the signification of <code>+</code>, <code>-</code>, <code>*</code>, etc. changes depending on the types of the operands (numerics, vectors, quantum wave functions, matrices, etc.).</p> <p>Most of us, as part of our science courses, learned multiple significations for operators, depending on the types of the operands. Did we find them confusing, them?</p> <h2>Operator overloading depends on its operands</h2> <p>This is the most important part of operator overloading: Like in mathematics, or in physics, the operation depends on its operands' types.</p> <p>So, know the type of the operand, and you will know the effect of the operation.</p> <h2>Even C and Java have (hardcoded) operator overloading</h2> <p>In C, the real behavior of an operator will change according to its operands. For example, adding two integers is different than adding two doubles, or even one integer and one double. There is even the whole pointer arithmetic domain (without casting, you can add to a pointer an integer, but you cannot add two pointers…).</p> <p>In Java, there is no pointer arithmetics, but someone still found string concatenation without the <code>+</code> operator would be ridiculous enough to justify an exception in the «operator overloading is evil» creed.</p> <p>It’s just that you, as a C (for historical reasons) or Java (for <i>personal reasons</i>, see below) coder, you can’t provide your own.</p> <h2>In C++, operator overloading is not optional…</h2> <p>In C++, operator overloading for built-in types is not possible (and this is a good thing), but <i>user-defined</i> types can have <i>user-defined</i> operator overloads.</p> <p>As already said earlier, in C++, and to the contrary to Java, user-types are not considered second-class citizens of the language, when compared to built-in types. So, if built-in types have operators, user types should be able to have them, too.</p> <p>The truth is that, like the <code>toString()</code>, <code>clone()</code>, <code>equals()</code> methods are for Java (<i>i.e. quasi-standard-like</i>), C++ operator overloading is so much part of C++ that it becomes as natural as the original C operators, or the before mentioned Java methods.</p> <p>Combined with template programming, operator overloading becomes a well known design pattern. In fact, you cannot go very far in STL without using overloaded operators, and overloading operators for your own class.</p> <h2>…but it should not be abused</h2> <p>Operator overloading should strive to respect the semantics of the operator. Do not substract in a <code>+</code> operator (as in «do not substract in a <code>add</code> function», or «return crap in a <code>clone</code> method»).</p> <p>Cast overloading can be very dangerous because they can lead to ambiguities. So they should really be reserved for well defined cases. As for <code>&amp;&amp;</code> and <code>||</code>, do not ever overload them unless you really know what you’re doing, as you’ll loose the the short circuit evaluation that the native operators <code>&amp;&amp;</code> and <code>||</code> enjoy.</p> <h1>So… Ok… Then why it is not possible in Java?</h1> <p>Because James Gosling said so:</p> <blockquote> <p>I left out operator overloading as a <b>fairly personal choice</b> because I had seen too many people abuse it in C++.</p> <p><i>James Gosling. Source: <a href="http://www.gotw.ca/publications/c_family_interview.htm" rel="nofollow">http://www.gotw.ca/publications/c_family_interview.htm</a></i></p> </blockquote> <p>Please compare Gosling’s text above with Stroustrup’s below:</p> <blockquote> <p>Many C++ design decisions have their roots in my dislike for forcing people to do things in some particular way […] Often, I was tempted to outlaw a feature I personally disliked, I refrained from doing so because <b>I did not think I had the right to force my views on others</b>.</p> <p><i>Bjarne Stroustrup. Source: The Desing and Evolution of C++ (1.3 General Background)</i></p> </blockquote> <h2>Would operator overloading benefit Java?</h2> <p>Some objects would greatly benefit from operator overloading (concrete or numerical types, like BigDecimal, complex numbers, matrices, containers, iterators, comparators, parsers etc.).</p> <p>In C++, you can profit from this benefit because of Stroustrup’s humility. In Java, you’re simply screwed because of Gosling’s <i>personal choice</i>.</p> <h2>Could it be added to Java?</h2> <p>The reasons for not adding operator overloading now in Java could be a mix of internal politics, allergy to the feature, distrust of developers (you know, the saboteur ones that seem to haunt Java teams…), compatibility with the previous JVMs, time to write a correct specification, etc..</p> <p>So don’t hold your breath waiting for this feature…</p> <h2>But they do it in C#!!!</h2> <p>Yeah…</p> <p>While this is far from being the only difference between the two languages, this one never fails to amuse me.</p> <p>Apparently, the C# folks, with their <i>«every primitive is a <code>struct</code>, and a <code>struct</code> derives from Object»</i>, got it right at first try.</p></html>
+
*: {{WikiACutBegin|...}}<html><p>There are a lot of posts complaining about operator overloading.</p> <p>I felt I had to clarify the «operator overloading» concepts, offering an alternative viewpoint on this concept.</p> <h1>Code obfuscating?</h1> <p>This argument is a fallacy.</p> <h2>Obfuscating is possible in all languages…</h2> <p>It is as easy to obfuscate code in C or Java through functions/methods than it is in C++ through operator overloads:</p> <pre class="default prettyprint"><code><span class="com">// C++</span><span class="pln"><br>T </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="com">// add ?</span><span class="pln"><br></span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp;T c </span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp;c</span><span class="pun">.</span><span class="pln">value </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">value </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">value </span><span class="pun">;</span><span class="pln"> </span><span class="com">// substract !!!</span><span class="pln"><br>&nbsp; &nbsp;</span><span class="kwd">return</span><span class="pln"> c </span><span class="pun">;</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br></span><span class="com">// Java</span><span class="pln"><br></span><span class="kwd">static</span><span class="pln"> T add </span><span class="pun">(</span><span class="pln">T a</span><span class="pun">,</span><span class="pln"> T b</span><span class="pun">)</span><span class="pln"> </span><span class="com">// add ?</span><span class="pln"><br></span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp;T c </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> T</span><span class="pun">()</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp;c</span><span class="pun">.</span><span class="pln">value </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">value </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">value </span><span class="pun">;</span><span class="pln"> </span><span class="com">// substract !!!</span><span class="pln"><br>&nbsp; &nbsp;</span><span class="kwd">return</span><span class="pln"> c </span><span class="pun">;</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br></span><span class="com">/* C */</span><span class="pln"><br>T add </span><span class="pun">(</span><span class="pln">T a</span><span class="pun">,</span><span class="pln"> T b</span><span class="pun">)</span><span class="pln"> </span><span class="com">/* add ? */</span><span class="pln"><br></span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp;T c </span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp;c</span><span class="pun">.</span><span class="pln">value </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">value </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">value </span><span class="pun">;</span><span class="pln"> </span><span class="com">/* substract !!! */</span><span class="pln"><br>&nbsp; &nbsp;</span><span class="kwd">return</span><span class="pln"> c </span><span class="pun">;</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br></span></code></pre> <h2>…Even in Java’s standard interfaces</h2> <p>For another example, let’s see the <code>Cloneable</code> interface in Java: <a href="http://download.oracle.com/javase/7/docs/api/java/lang/Cloneable.html" rel="nofollow">http://download.oracle.com/javase/7/docs/api/java/lang/Cloneable.html</a></p>  <p>You are supposed to clone the object implementing this interface. But you could lie. And create a different object. In fact, this interface is so weak you could return another type of object altogether, just for the fun of it:</p> <pre class="default prettyprint"><code><span class="kwd">class</span><span class="pln"> </span><span class="typ">MySincereHandShake</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><span class="typ">Cloneable</span><span class="pln"><br></span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">Object</span><span class="pln"> clone</span><span class="pun">()</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; &nbsp;</span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MyVengefulKickInYourHead</span><span class="pun">()</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp; </span><span class="pun">}</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br></span></code></pre> <p>As the <code>Cloneable</code> interface can be abused/obfuscated, should it be banned on the same grounds C++ operator overloading are supposed to be?</p> <p>We could overload the <code>toString()</code> method of a <code>MyComplexNumber</code> class to have it return the stringified hour of the day. Should the <code>toString()</code> overloading be banned, too? We could sabotage <code>MyComplexNumber.equals</code> to have it return a random value, modify the operands… etc. etc. etc..</p> <p><b>In Java, as in C++, or whatever language, the programmer must respect a minimum of semantics when writing code. This means implementing a <code>add</code> function that adds, and <code>Cloneable</code> implementation method that clones, and a <code>++</code> operator than increments.</b></p> <h1>What’s obfuscating anyway?</h1> <p>Now that we know that code can be sabotaged even through the pristine Java methods, we can ask ourselves about the real use of operator overloading in C++?</p> <h2>Clear and natural notation: methods vs. operator overloading?</h2> <p>We’ll compare below, for different cases, the «same» code in Java and C++, to have an idea of which kind of coding style is clearer.</p> <h3>Natural comparisons:</h3> <pre class="default prettyprint"><code><span class="com">// C++ comparison for built-ins and user-defined types</span><span class="pln"><br></span><span class="kwd">bool</span><span class="pln"> &nbsp; &nbsp;isEqual &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="pun">=</span><span class="pln"> A </span><span class="pun">==</span><span class="pln"> B </span><span class="pun">;</span><span class="pln"><br></span><span class="kwd">bool</span><span class="pln"> &nbsp; &nbsp;isNotEqual &nbsp; &nbsp; &nbsp; </span><span class="pun">=</span><span class="pln"> A </span><span class="pun">!=</span><span class="pln"> B </span><span class="pun">;</span><span class="pln"><br></span><span class="kwd">bool</span><span class="pln"> &nbsp; &nbsp;isLesser &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="pun">=</span><span class="pln"> A </span><span class="pun">&lt;</span><span class="pln"> &nbsp;B </span><span class="pun">;</span><span class="pln"><br></span><span class="kwd">bool</span><span class="pln"> &nbsp; &nbsp;isLesserOrEqual &nbsp;</span><span class="pun">=</span><span class="pln"> A </span><span class="pun">&lt;=</span><span class="pln"> B </span><span class="pun">;</span><span class="pln"><br><br></span><span class="com">// Java comparison for user-defined types</span><span class="pln"><br></span><span class="kwd">boolean</span><span class="pln"> isEqual &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="pun">=</span><span class="pln"> A</span><span class="pun">.</span><span class="pln">equals</span><span class="pun">(</span><span class="pln">B</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br></span><span class="kwd">boolean</span><span class="pln"> isNotEqual &nbsp; &nbsp; &nbsp; </span><span class="pun">=</span><span class="pln"> </span><span class="pun">!</span><span class="pln"> A</span><span class="pun">.</span><span class="pln">equals</span><span class="pun">(</span><span class="pln">B</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br></span><span class="kwd">boolean</span><span class="pln"> isLesser &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="pun">=</span><span class="pln"> A</span><span class="pun">.</span><span class="pln">comparesTo</span><span class="pun">(</span><span class="pln">B</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br></span><span class="kwd">boolean</span><span class="pln"> isLesserOrEqual &nbsp;</span><span class="pun">=</span><span class="pln"> A</span><span class="pun">.</span><span class="pln">comparesTo</span><span class="pun">(</span><span class="pln">B</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br></span></code></pre> <p>Please note that A and B could be of any type in C++, as long as the operator overloads are provided. In Java, when A and B are not primitives, the code can become very confusing, even for primitive-like objects (BigInteger, etc.)…</p> <h3>Natural array/container accessors and subscripting:</h3> <pre class="default prettyprint"><code><span class="com">// C++ container accessors, more natural</span><span class="pln"><br>value &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="pun">=</span><span class="pln"> myArray</span><span class="pun">[</span><span class="lit">25</span><span class="pun">]</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// subscript operator</span><span class="pln"><br>value &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="pun">=</span><span class="pln"> myVector</span><span class="pun">[</span><span class="lit">25</span><span class="pun">]</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="com">// subscript operator</span><span class="pln"><br>value &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="pun">=</span><span class="pln"> myString</span><span class="pun">[</span><span class="lit">25</span><span class="pun">]</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="com">// subscript operator</span><span class="pln"><br>value &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="pun">=</span><span class="pln"> myMap</span><span class="pun">[</span><span class="str">«25»</span><span class="pun">]</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// subscript operator</span><span class="pln"><br>myArray</span><span class="pun">[</span><span class="lit">25</span><span class="pun">]</span><span class="pln"> &nbsp;</span><span class="pun">=</span><span class="pln"> value </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// subscript operator</span><span class="pln"><br>myVector</span><span class="pun">[</span><span class="lit">25</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> value </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// subscript operator</span><span class="pln"><br>myString</span><span class="pun">[</span><span class="lit">25</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> value </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// subscript operator</span><span class="pln"><br>myMap</span><span class="pun">[</span><span class="str">«25»</span><span class="pun">]</span><span class="pln"> &nbsp;</span><span class="pun">=</span><span class="pln"> value </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// subscript operator</span><span class="pln"><br><br></span><span class="com">// Java container accessors, each one has its special notation</span><span class="pln"><br>value &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="pun">=</span><span class="pln"> myArray</span><span class="pun">[</span><span class="lit">25</span><span class="pun">]</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// subscript operator</span><span class="pln"><br>value &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="pun">=</span><span class="pln"> myVector</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="lit">25</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp;</span><span class="com">// method get</span><span class="pln"><br>value &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="pun">=</span><span class="pln"> myString</span><span class="pun">.</span><span class="pln">charAt</span><span class="pun">(</span><span class="lit">25</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> </span><span class="com">// method charAt</span><span class="pln"><br>value &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="pun">=</span><span class="pln"> myMap</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="str">«25»</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; </span><span class="com">// method get</span><span class="pln"><br>myArray</span><span class="pun">[</span><span class="lit">25</span><span class="pun">]</span><span class="pln"> &nbsp;</span><span class="pun">=</span><span class="pln"> value </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// subscript operator</span><span class="pln"><br>myVector</span><span class="pun">.</span><span class="kwd">set</span><span class="pun">(</span><span class="lit">25</span><span class="pun">,</span><span class="pln"> value</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="com">// method set</span><span class="pln"><br>myMap</span><span class="pun">.</span><span class="kwd">set</span><span class="pun">(</span><span class="str">«25»</span><span class="pun">,</span><span class="pln"> value</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// method set</span><span class="pln"><br></span></code></pre> <p>In Java, we see that for each container to do the same thing (access its content through an index or identifier), we have a different way to do it, which is confusing.</p> <p>In C++, each container uses the same way to access its content, thanks to operator overload.</p> <h3>Natural advanced types manipulation</h3> <p>The examples below use a <code>Matrix</code> object, found using the first links found on Google for «<a href=»https://encrypted.google.com/search?q=Java+Matrix+object" rel="nofollow">Java Matrix object</a>" and «<a href=»https://encrypted.google.com/search?q=c%2B%2B+Matrix+object" rel="nofollow">c++ Matrix object</a>":</p> <pre class="default prettyprint"><code><span class="com">// C++ YMatrix matrix implementation on CodeProject</span><span class="pln"><br></span><span class="com">// http://www.codeproject.com/KB/architecture/ymatrix.aspx</span><span class="pln"><br></span><span class="com">// A, B, C, D, E, F are Matrix objects;</span><span class="pln"><br>E </span><span class="pun">=</span><span class="pln"> &nbsp;A </span><span class="pun">*</span><span class="pln"> </span><span class="pun">(</span><span class="pln">B </span><span class="pun">/</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>E </span><span class="pun">+=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">A </span><span class="pun">-</span><span class="pln"> B</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">(</span><span class="pln">C </span><span class="pun">+</span><span class="pln"> D</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>F </span><span class="pun">=</span><span class="pln"> &nbsp;E </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="com">// deep copy of the matrix</span><span class="pln"><br><br></span><span class="com">// Java JAMA matrix implementation (seriously…)</span><span class="pln"><br></span><span class="com">// http://math.nist.gov/javanumerics/jama/doc/</span><span class="pln"><br></span><span class="com">// A, B, C, D, E, F are Matrix objects;</span><span class="pln"><br>E </span><span class="pun">=</span><span class="pln"> A</span><span class="pun">.</span><span class="pln">times</span><span class="pun">(</span><span class="pln">B</span><span class="pun">.</span><span class="pln">times</span><span class="pun">(</span><span class="lit">2</span><span class="pun">))</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>E</span><span class="pun">.</span><span class="pln">plusEquals</span><span class="pun">(</span><span class="pln">A</span><span class="pun">.</span><span class="pln">minus</span><span class="pun">(</span><span class="pln">B</span><span class="pun">).</span><span class="pln">times</span><span class="pun">(</span><span class="pln">C</span><span class="pun">.</span><span class="pln">plus</span><span class="pun">(</span><span class="pln">D</span><span class="pun">)))</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>F </span><span class="pun">=</span><span class="pln"> E</span><span class="pun">.</span><span class="pln">copy</span><span class="pun">()</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="com">// deep copy of the matrix</span><span class="pln"><br></span></code></pre> <p>And this is not limited to matrices. The <code>BigInteger</code> and <code>BigDecimal</code> classes of Java suffer from the same confusing verbosity, whereas their equivalent in C++ are as clear as built-in types.</p> <h3>Natural iterators:</h3> <pre class="default prettyprint"><code><span class="com">// C++ Random Access iterators</span><span class="pln"><br></span><span class="pun">++</span><span class="pln">it </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="com">// move to the next item</span><span class="pln"><br></span><span class="pun">--</span><span class="pln">it </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="com">// move to the previous item</span><span class="pln"><br>it </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// move to the next 5th item (random access)</span><span class="pln"><br>value </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*</span><span class="pln">it </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// gets the value of the current item</span><span class="pln"><br></span><span class="pun">*</span><span class="pln">it </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3.1415</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="com">// sets the value 3.1415 to the current item</span><span class="pln"><br></span><span class="pun">(*</span><span class="pln">it</span><span class="pun">).</span><span class="pln">foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="com">// call method foo() of the current item</span><span class="pln"><br><br></span><span class="com">// Java ListIterator&lt;E&gt; «bi-directional» iterators</span><span class="pln"><br>value </span><span class="pun">=</span><span class="pln"> it</span><span class="pun">.</span><span class="kwd">next</span><span class="pun">()</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; </span><span class="com">// move to the next item &amp; return the value</span><span class="pln"><br>value </span><span class="pun">=</span><span class="pln"> it</span><span class="pun">.</span><span class="pln">previous</span><span class="pun">()</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> </span><span class="com">// move to the previous item &amp; return the value</span><span class="pln"><br>it</span><span class="pun">.</span><span class="kwd">set</span><span class="pun">(</span><span class="lit">3.1415</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> &nbsp; &nbsp; &nbsp; &nbsp;</span><span class="com">// sets the value 3.1415 to the current item</span><span class="pln"><br></span></code></pre> <h3>Natural functors:</h3> <pre class="default prettyprint"><code><span class="com">// C++ Functors</span><span class="pln"><br>myFunctorObject</span><span class="pun">(</span><span class="str">«Hello World»</span><span class="pun">,</span><span class="pln"> </span><span class="lit">42</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br><br></span><span class="com">// Java Functors ???</span><span class="pln"><br>myFunctorObject</span><span class="pun">.</span><span class="pln">execute</span><span class="pun">(</span><span class="str">«Hello World»</span><span class="pun">,</span><span class="pln"> </span><span class="lit">42</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br></span></code></pre> <h3>Text concatenation:</h3> <pre class="default prettyprint"><code><span class="com">// C++ stream handling (with the &lt;&lt; operator)</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stringStream &nbsp; </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Hello "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">25</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">« World»</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fileStream &nbsp; &nbsp; </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Hello "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">25</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">« World»</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; outputStream &nbsp; </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Hello "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">25</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">« World»</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; networkStream &nbsp;</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Hello "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">25</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">« World»</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>anythingThatOverloadsShiftOperator </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Hello "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">25</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">« World»</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br><br></span><span class="com">// Java concatenation</span><span class="pln"><br>myStringBuffer</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="str">"Hello "</span><span class="pun">).</span><span class="pln">append</span><span class="pun">(</span><span class="lit">25</span><span class="pun">).</span><span class="pln">append</span><span class="pun">(</span><span class="str">« World»</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br></span></code></pre> <p>Ok, in Java you can use <code>MyString = "Hello " + 25 + « World» ;</code> too… But, wait a second: This is operator overloading, isn’t it? Isn’t it cheating???</p> <p>:-D</p> <h2>Generic code?</h2> <p>The same generic code modifying operands should be usable both for built-ins/primitives (which have no interfaces in Java), standard objects (which could not have the right interface), and user-defined objects.</p> <p>For example, calculating the average value of two values of arbitrary types:</p> <pre class="default prettyprint"><code><span class="com">// C++ primitive/advanced types</span><span class="pln"><br></span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln"><br>T getAverage</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> p_lhs</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> p_rhs</span><span class="pun">)</span><span class="pln"><br></span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp;</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">p_lhs </span><span class="pun">+</span><span class="pln"> p_rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br></span><span class="kwd">int</span><span class="pln"> &nbsp; &nbsp; intValue &nbsp; &nbsp; </span><span class="pun">=</span><span class="pln"> getAverage</span><span class="pun">(</span><span class="lit">25</span><span class="pun">,</span><span class="pln"> </span><span class="lit">42</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br></span><span class="kwd">double</span><span class="pln"> &nbsp;doubleValue &nbsp;</span><span class="pun">=</span><span class="pln"> getAverage</span><span class="pun">(</span><span class="lit">25.25</span><span class="pun">,</span><span class="pln"> </span><span class="lit">42.42</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"><br>complex complexValue </span><span class="pun">=</span><span class="pln"> getAverage</span><span class="pun">(</span><span class="pln">cA</span><span class="pun">,</span><span class="pln"> cB</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> </span><span class="com">// cA, cB are complex</span><span class="pln"><br></span><span class="typ">Matrix</span><span class="pln"> &nbsp;matrixValue &nbsp;</span><span class="pun">=</span><span class="pln"> getAverage</span><span class="pun">(</span><span class="pln">mA</span><span class="pun">,</span><span class="pln"> mB</span><span class="pun">)</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> </span><span class="com">// mA, mB are Matrix</span><span class="pln"><br><br></span><span class="com">// Java primitive/advanced types</span><span class="pln"><br></span><span class="com">// It won’t really work in Java, even with generics. Sorry.</span><span class="pln"><br></span></code></pre> <h1>Discussing operator overloading</h1> <p>How that we saw fair comparisons between C++ code using operator overloading, and the same code in Java, we can know discuss the «operator overloading» as a concept.</p> <h2>Operator overloading existed since before computers</h2> <p><b>Even outside of computer science, there are operator overloading: For example, in mathematics, operators like <code>+</code>, <code>-</code>, <code>*</code>, etc. are overloaded.</b></p> <p>Indeed, the signification of <code>+</code>, <code>-</code>, <code>*</code>, etc. changes depending on the types of the operands (numerics, vectors, quantum wave functions, matrices, etc.).</p> <p>Most of us, as part of our science courses, learned multiple significations for operators, depending on the types of the operands. Did we find them confusing, them?</p> <h2>Operator overloading depends on its operands</h2> <p>This is the most important part of operator overloading: Like in mathematics, or in physics, the operation depends on its operands' types.</p> <p>So, know the type of the operand, and you will know the effect of the operation.</p> <h2>Even C and Java have (hardcoded) operator overloading</h2> <p>In C, the real behavior of an operator will change according to its operands. For example, adding two integers is different than adding two doubles, or even one integer and one double. There is even the whole pointer arithmetic domain (without casting, you can add to a pointer an integer, but you cannot add two pointers…).</p> <p>In Java, there is no pointer arithmetics, but someone still found string concatenation without the <code>+</code> operator would be ridiculous enough to justify an exception in the «operator overloading is evil» creed.</p> <p>It’s just that you, as a C (for historical reasons) or Java (for <i>personal reasons</i>, see below) coder, you can’t provide your own.</p> <h2>In C++, operator overloading is not optional…</h2> <p>In C++, operator overloading for built-in types is not possible (and this is a good thing), but <i>user-defined</i> types can have <i>user-defined</i> operator overloads.</p> <p>As already said earlier, in C++, and to the contrary to Java, user-types are not considered second-class citizens of the language, when compared to built-in types. So, if built-in types have operators, user types should be able to have them, too.</p> <p>The truth is that, like the <code>toString()</code>, <code>clone()</code>, <code>equals()</code> methods are for Java (<i>i.e. quasi-standard-like</i>), C++ operator overloading is so much part of C++ that it becomes as natural as the original C operators, or the before mentioned Java methods.</p> <p>Combined with template programming, operator overloading becomes a well known design pattern. In fact, you cannot go very far in STL without using overloaded operators, and overloading operators for your own class.</p> <h2>…but it should not be abused</h2> <p>Operator overloading should strive to respect the semantics of the operator. Do not substract in a <code>+</code> operator (as in «do not substract in a <code>add</code> function», or «return crap in a <code>clone</code> method»).</p> <p>Cast overloading can be very dangerous because they can lead to ambiguities. So they should really be reserved for well defined cases. As for <code>&amp;&amp;</code> and <code>||</code>, do not ever overload them unless you really know what you’re doing, as you’ll loose the the short circuit evaluation that the native operators <code>&amp;&amp;</code> and <code>||</code> enjoy.</p> <h1>So… Ok… Then why it is not possible in Java?</h1> <p>Because James Gosling said so:</p> <blockquote> <p>I left out operator overloading as a <b>fairly personal choice</b> because I had seen too many people abuse it in C++.</p> <p><i>James Gosling. Source: <a href="http://www.gotw.ca/publications/c_family_interview.htm" rel="nofollow">http://www.gotw.ca/publications/c_family_interview.htm</a></i></p> </blockquote> <p>Please compare Gosling’s text above with Stroustrup’s below:</p> <blockquote> <p>Many C++ design decisions have their roots in my dislike for forcing people to do things in some particular way […] Often, I was tempted to outlaw a feature I personally disliked, I refrained from doing so because <b>I did not think I had the right to force my views on others</b>.</p> <p><i>Bjarne Stroustrup. Source: The Desing and Evolution of C++ (1.3 General Background)</i></p> </blockquote> <h2>Would operator overloading benefit Java?</h2> <p>Some objects would greatly benefit from operator overloading (concrete or numerical types, like BigDecimal, complex numbers, matrices, containers, iterators, comparators, parsers etc.).</p> <p>In C++, you can profit from this benefit because of Stroustrup’s humility. In Java, you’re simply screwed because of Gosling’s <i>personal choice</i>.</p> <h2>Could it be added to Java?</h2> <p>The reasons for not adding operator overloading now in Java could be a mix of internal politics, allergy to the feature, distrust of developers (you know, the saboteur ones that seem to haunt Java teams…), compatibility with the previous JVMs, time to write a correct specification, etc..</p> <p>So don’t hold your breath waiting for this feature…</p> <h2>But they do it in C#!!!</h2> <p>Yeah…</p> <p>While this is far from being the only difference between the two languages, this one never fails to amuse me.</p> <p>Apparently, the C# folks, with their <i>«every primitive is a <code>struct</code>, and a <code>struct</code> derives from Object»</i>, got it right at first try.</p></html>{{WikiCutEnd}}
 
<!-- NEXT BOOKMARK -->
 
<!-- NEXT BOOKMARK -->
 
* 07 Ноябрь, 14:40:11: [http://www.sweethome3d.com/ru/index.jsp Sweet Home 3D]
 
* 07 Ноябрь, 14:40:11: [http://www.sweethome3d.com/ru/index.jsp Sweet Home 3D]

Версия 18:32, 16 января 2012

Rss16.png На мои закладки можно подписаться по RSS — просто кликните по ссылке.

2012

Январь 2012

2011

Декабрь 2011

Ноябрь 2011

  • 30 Ноябрь, 19:39:49: Open-Source ~ Why The GIMP's User Interface Is Not As Terrible As You May Think
  • 30 Ноябрь, 01:56:54: Лечим недостаточную поворачиваемость
  • 28 Ноябрь, 16:05:05: WHBT. Ремонт Бытовой Техники. :: Просмотр темы - Барабан Ardo FLS105L :: Ремонт стиральных машин, холодильников, кухонных плит.
  • 18 Ноябрь, 19:19:55: MP3 Player
  • 18 Ноябрь, 19:00:24: Dewplayer lecteur mp3 en Flash - Alsacréations
  • 17 Ноябрь, 23:26:41: glue-it.com --> Model Making
  • 15 Ноябрь, 14:48:25: Light Racer 2.0 - Days 32-33 - Getting Great Game Performance | Robert Green's DIY
  • 14 Ноябрь, 18:19:54: The Bulbdial Clock Kit — Evil Mad Scientist Laboratories
  • 14 Ноябрь, 02:47:58: Список алгоритмов и структур данных на C++ — Algorithms in Java
  • 11 Ноябрь, 11:19:06: #270852 — iptables: (patch) to add userspace support for kernel patch per-program per-connection filtering — Debian Bug report logs
  • 10 Ноябрь, 23:55:26: 97794_beregovaya-ohrana.jpg (760×575)
  • 10 Ноябрь, 00:21:10: Компонент-Реактив | Компонент-Реактив
  • 09 Ноябрь, 12:38:57: Группа компаний «РусХим»
  • 09 Ноябрь, 03:33:43: c++ — Java operator overload — Stack Overflow
    Шаблон:WikiACutBegin

    There are a lot of posts complaining about operator overloading.

    I felt I had to clarify the «operator overloading» concepts, offering an alternative viewpoint on this concept.

    Code obfuscating?

    This argument is a fallacy.

    Obfuscating is possible in all languages…

    It is as easy to obfuscate code in C or Java through functions/methods than it is in C++ through operator overloads:

    // C++
    T
    operator + (const T & a, const T & b) // add ?
    {
       T c
    ;
       c
    .value = a.value - b.value ; // substract !!!
       
    return c ;
    }

    // Java
    static T add (T a, T b) // add ?
    {
       T c
    = new T() ;
       c
    .value = a.value - b.value ; // substract !!!
       
    return c ;
    }

    /* C */
    T add
    (T a, T b) /* add ? */
    {
       T c
    ;
       c
    .value = a.value - b.value ; /* substract !!! */
       
    return c ;
    }

    …Even in Java’s standard interfaces

    For another example, let’s see the Cloneable interface in Java: http://download.oracle.com/javase/7/docs/api/java/lang/Cloneable.html

    You are supposed to clone the object implementing this interface. But you could lie. And create a different object. In fact, this interface is so weak you could return another type of object altogether, just for the fun of it:

    class MySincereHandShake implements Cloneable
    {
       
    public Object clone()
       
    {
           
    return new MyVengefulKickInYourHead() ;
       
    }
    }

    As the Cloneable interface can be abused/obfuscated, should it be banned on the same grounds C++ operator overloading are supposed to be?

    We could overload the toString() method of a MyComplexNumber class to have it return the stringified hour of the day. Should the toString() overloading be banned, too? We could sabotage MyComplexNumber.equals to have it return a random value, modify the operands… etc. etc. etc..

    In Java, as in C++, or whatever language, the programmer must respect a minimum of semantics when writing code. This means implementing a add function that adds, and Cloneable implementation method that clones, and a ++ operator than increments.

    What’s obfuscating anyway?

    Now that we know that code can be sabotaged even through the pristine Java methods, we can ask ourselves about the real use of operator overloading in C++?

    Clear and natural notation: methods vs. operator overloading?

    We’ll compare below, for different cases, the «same» code in Java and C++, to have an idea of which kind of coding style is clearer.

    Natural comparisons:

    // C++ comparison for built-ins and user-defined types
    bool    isEqual          = A == B ;
    bool    isNotEqual       = A != B ;
    bool    isLesser         = A <  B ;
    bool    isLesserOrEqual  = A <= B ;

    // Java comparison for user-defined types
    boolean isEqual          = A.equals(B) ;
    boolean isNotEqual       = ! A.equals(B) ;
    boolean isLesser         = A.comparesTo(B) < 0 ;
    boolean isLesserOrEqual  = A.comparesTo(B) <= 0 ;

    Please note that A and B could be of any type in C++, as long as the operator overloads are provided. In Java, when A and B are not primitives, the code can become very confusing, even for primitive-like objects (BigInteger, etc.)…

    Natural array/container accessors and subscripting:

    // C++ container accessors, more natural
    value        
    = myArray[25] ;         // subscript operator
    value        
    = myVector[25] ;        // subscript operator
    value        
    = myString[25] ;        // subscript operator
    value        
    = myMap[«25»] ;         // subscript operator
    myArray
    [25]  = value ;               // subscript operator
    myVector
    [25] = value ;               // subscript operator
    myString
    [25] = value ;               // subscript operator
    myMap
    [«25»]  = value ;               // subscript operator

    // Java container accessors, each one has its special notation
    value        
    = myArray[25] ;         // subscript operator
    value        
    = myVector.get(25) ;    // method get
    value        
    = myString.charAt(25) ; // method charAt
    value        
    = myMap.get(«25») ;     // method get
    myArray
    [25]  = value ;               // subscript operator
    myVector
    .set(25, value) ;            // method set
    myMap
    .set(«25», value) ;             // method set

    In Java, we see that for each container to do the same thing (access its content through an index or identifier), we have a different way to do it, which is confusing.

    In C++, each container uses the same way to access its content, thanks to operator overload.

    Natural advanced types manipulation

    The examples below use a Matrix object, found using the first links found on Google for «Java Matrix object" and «c++ Matrix object":

    // C++ YMatrix matrix implementation on CodeProject
    // http://www.codeproject.com/KB/architecture/ymatrix.aspx
    // A, B, C, D, E, F are Matrix objects;
    E
    =  A * (B / 2) ;
    E
    += (A - B) * (C + D) ;
    F
    =  E ;                  // deep copy of the matrix

    // Java JAMA matrix implementation (seriously…)
    // http://math.nist.gov/javanumerics/jama/doc/
    // A, B, C, D, E, F are Matrix objects;
    E
    = A.times(B.times(2)) ;
    E
    .plusEquals(A.minus(B).times(C.plus(D))) ;
    F
    = E.copy() ;            // deep copy of the matrix

    And this is not limited to matrices. The BigInteger and BigDecimal classes of Java suffer from the same confusing verbosity, whereas their equivalent in C++ are as clear as built-in types.

    Natural iterators:

    // C++ Random Access iterators
    ++it ;                  // move to the next item
    --it ;                  // move to the previous item
    it
    += 5 ;               // move to the next 5th item (random access)
    value
    = *it ;           // gets the value of the current item
    *it = 3.1415 ;          // sets the value 3.1415 to the current item
    (*it).foo() ;           // call method foo() of the current item

    // Java ListIterator<E> «bi-directional» iterators
    value
    = it.next() ;     // move to the next item & return the value
    value
    = it.previous() ; // move to the previous item & return the value
    it
    .set(3.1415) ;        // sets the value 3.1415 to the current item

    Natural functors:

    // C++ Functors
    myFunctorObject
    («Hello World», 42) ;

    // Java Functors ???
    myFunctorObject
    .execute(«Hello World», 42) ;

    Text concatenation:

    // C++ stream handling (with the << operator)
                        stringStream  
    << "Hello " << 25 << « World» ;
                        fileStream    
    << "Hello " << 25 << « World» ;
                        outputStream  
    << "Hello " << 25 << « World» ;
                        networkStream  
    << "Hello " << 25 << « World» ;
    anythingThatOverloadsShiftOperator
    << "Hello " << 25 << « World» ;

    // Java concatenation
    myStringBuffer
    .append("Hello ").append(25).append(« World») ;

    Ok, in Java you can use MyString = "Hello " + 25 + « World» ; too… But, wait a second: This is operator overloading, isn’t it? Isn’t it cheating???

    :-D

    Generic code?

    The same generic code modifying operands should be usable both for built-ins/primitives (which have no interfaces in Java), standard objects (which could not have the right interface), and user-defined objects.

    For example, calculating the average value of two values of arbitrary types:

    // C++ primitive/advanced types
    template<typename T>
    T getAverage
    (const T & p_lhs, const T & p_rhs)
    {
       
    return (p_lhs + p_rhs) / 2 ;
    }

    int     intValue     = getAverage(25, 42) ;
    double  doubleValue  = getAverage(25.25, 42.42) ;
    complex complexValue
    = getAverage(cA, cB) ; // cA, cB are complex
    Matrix  matrixValue  = getAverage(mA, mB) ; // mA, mB are Matrix

    // Java primitive/advanced types
    // It won’t really work in Java, even with generics. Sorry.

    Discussing operator overloading

    How that we saw fair comparisons between C++ code using operator overloading, and the same code in Java, we can know discuss the «operator overloading» as a concept.

    Operator overloading existed since before computers

    Even outside of computer science, there are operator overloading: For example, in mathematics, operators like +, -, *, etc. are overloaded.

    Indeed, the signification of +, -, *, etc. changes depending on the types of the operands (numerics, vectors, quantum wave functions, matrices, etc.).

    Most of us, as part of our science courses, learned multiple significations for operators, depending on the types of the operands. Did we find them confusing, them?

    Operator overloading depends on its operands

    This is the most important part of operator overloading: Like in mathematics, or in physics, the operation depends on its operands' types.

    So, know the type of the operand, and you will know the effect of the operation.

    Even C and Java have (hardcoded) operator overloading

    In C, the real behavior of an operator will change according to its operands. For example, adding two integers is different than adding two doubles, or even one integer and one double. There is even the whole pointer arithmetic domain (without casting, you can add to a pointer an integer, but you cannot add two pointers…).

    In Java, there is no pointer arithmetics, but someone still found string concatenation without the + operator would be ridiculous enough to justify an exception in the «operator overloading is evil» creed.

    It’s just that you, as a C (for historical reasons) or Java (for personal reasons, see below) coder, you can’t provide your own.

    In C++, operator overloading is not optional…

    In C++, operator overloading for built-in types is not possible (and this is a good thing), but user-defined types can have user-defined operator overloads.

    As already said earlier, in C++, and to the contrary to Java, user-types are not considered second-class citizens of the language, when compared to built-in types. So, if built-in types have operators, user types should be able to have them, too.

    The truth is that, like the toString(), clone(), equals() methods are for Java (i.e. quasi-standard-like), C++ operator overloading is so much part of C++ that it becomes as natural as the original C operators, or the before mentioned Java methods.

    Combined with template programming, operator overloading becomes a well known design pattern. In fact, you cannot go very far in STL without using overloaded operators, and overloading operators for your own class.

    …but it should not be abused

    Operator overloading should strive to respect the semantics of the operator. Do not substract in a + operator (as in «do not substract in a add function», or «return crap in a clone method»).

    Cast overloading can be very dangerous because they can lead to ambiguities. So they should really be reserved for well defined cases. As for && and ||, do not ever overload them unless you really know what you’re doing, as you’ll loose the the short circuit evaluation that the native operators && and || enjoy.

    So… Ok… Then why it is not possible in Java?

    Because James Gosling said so:

    I left out operator overloading as a fairly personal choice because I had seen too many people abuse it in C++.

    James Gosling. Source: http://www.gotw.ca/publications/c_family_interview.htm

    Please compare Gosling’s text above with Stroustrup’s below:

    Many C++ design decisions have their roots in my dislike for forcing people to do things in some particular way […] Often, I was tempted to outlaw a feature I personally disliked, I refrained from doing so because I did not think I had the right to force my views on others.

    Bjarne Stroustrup. Source: The Desing and Evolution of C++ (1.3 General Background)

    Would operator overloading benefit Java?

    Some objects would greatly benefit from operator overloading (concrete or numerical types, like BigDecimal, complex numbers, matrices, containers, iterators, comparators, parsers etc.).

    In C++, you can profit from this benefit because of Stroustrup’s humility. In Java, you’re simply screwed because of Gosling’s personal choice.

    Could it be added to Java?

    The reasons for not adding operator overloading now in Java could be a mix of internal politics, allergy to the feature, distrust of developers (you know, the saboteur ones that seem to haunt Java teams…), compatibility with the previous JVMs, time to write a correct specification, etc..

    So don’t hold your breath waiting for this feature…

    But they do it in C#!!!

    Yeah…

    While this is far from being the only difference between the two languages, this one never fails to amuse me.

    Apparently, the C# folks, with their «every primitive is a struct, and a struct derives from Object», got it right at first try.

  • 07 Ноябрь, 14:40:11: Sweet Home 3D
  • 07 Ноябрь, 01:41:35: HeliSimRC
  • 04 Ноябрь, 19:34:32: How To Disable Google’s Personalization Of Search Results
  • 01 Ноябрь, 21:41:00: How to hack Acoms AS-16 servos — Blog — Jamie Matthews
  • Октябрь 2011

    Сентябрь 2011

    Август 2011


    Июль 2011

    Июнь 2011

    Май 2011

    Апрель 2011

    Март 2011

    Февраль 2011

    Январь 2011

    2010

    Декабрь 2010

    Ноябрь 2010

    Октябрь 2010

    Сентябрь 2010

    Август 2010

    Июль 2010

    Июнь 2010

    Май 2010

    Апрель 2010

    Март 2010

    Февраль 2010

    Январь 2010

    2009

    Декабрь 2009

    Октябрь 2009

    Сентябрь 2009

    Август 2009

    Июль 2009

    Июнь 2009

    Май 2009

    Апрель 2009

    Март 2009

    Февраль 2009

    Январь 2009

    2008

    Декабрь 2008

    Ноябрь 2008

    Октябрь 2008

    Сентябрь 2008

    Август 2008

    Июль 2008

    Июнь 2008

    Май 2008

    Апрель 2008

    Март 2008

    Февраль 2008

    Январь 2008

    2007

    Ноябрь 2007

    Октябрь 2007

    Сентябрь 2007

    Август 2007

    Июль 2007

    Апрель 2007

    Февраль 2007

    Январь 2007

    2006

    Декабрь 2006