### Language Comparisons http://ece.arizona.edu/~edatools/ece373/python/Comparisons/ - SourceForgeProjects.htm - number of new projects over the last 4 years - RubyPython.htm - comparing Ruby to Python ### Comparing Java to Python - a medium complexity example. AddablePolynomial is a subclass of Polynomial and Addable, representing a polynomial object to be added with other polynomial objects or an AddableInteger. The add() method must accept a single argument, either a Polynomial (which includes AddablePolynomials, or an AddableInteger). ## public class AddablePolynomial extends Polynomial implements Addable { /** * Add a Polynomial, despite the fact that it does not match our interface. * We do this by creating a new AddablePolynomial using the constructor. * * @param rhs The Polynomial to add to ourself. * @return */ public Addable add( Polynomial rhs ) { return this.add( (Addable)(new AddablePolynomial( rhs ) )); } /** * Returns the sum of this object plus rhs, iff rhs is of kind * AddablePolynomial or AddableInteger. *

* If the rhs does not match a known kind, * we return a 'null' value as the result of addition. * * @see distribution.hw03.Addable#add(Addable) * * @param rhs The right-hand-side of this+rhs * @return The result of this+rhs */ public Addable add( Addable rhs ) { Addable result = new AddablePolynomial( this ); if( rhs instanceof AddablePolynomial ) { AddablePolynomial rhsPoly = (AddablePolynomial)rhs; // we know the result is a poly, so, we // will go element by element of the rhs // Polynomial and add those elements to // the result one (or insert them if they // do not exist) // NOTE: not optimized for speed (e.g., if rhs >> result) List rhsExponents = rhsPoly.getSortedExponents(); for( Iterator it = rhsExponents.iterator(); it.hasNext(); ) { Integer key = it.next(); // add our element's coefficient to this one's double resultA = ((AddablePolynomial)result).getCoefficientByExponent(key); double rhsA = rhsPoly.getCoefficientByExponent(key); ((AddablePolynomial)result).setCoefficientByExponent( key, resultA + rhsA); } } else if( rhs instanceof AddableInteger ) { // add the integer's value to our 0th exponent's coefficient double value0 = ((AddablePolynomial)result).getCoefficientByExponent(0); double value1 = ((AddableInteger)rhs).getInteger().intValue(); ((AddablePolynomial)result).setCoefficientByExponent( 0, value0 + value1 ); } else { // we don't know what we're doing, return null result = null; } return result; } } Notes Line 20 return this.add( (Addable)(new AddablePolynomial( rhs ) )); Creates a new AddablePolynomial from a simple Polynomial, then upcasts the result to an Addable, so that it can be fed back to the add() method, this time going to the version which handles Addable arguments. 37 Addable result = new AddablePolynomial( this ); Creates a temporary result by cloning the current instance (an AddablePolynomial) and upcasting to Addable. Later (lines 52, 54, 60, and 62) we downcast to AddablePolynomial. ===> not sure why this is necessary === 40 AddablePolynomial rhsPoly = (AddablePolynomial)rhs; Downcasting to AddablePolynomial is necessary, even though line 37 ensures that rhs is already an AddablePolynomial. The compiler doesn't follow the logic seen at runtime. It just sees Addable rhs in the arguments to the method call. We must downcast to AddablePolynomial in order to assign the variable rhsPoly to this object. 48 List rhsExponents = rhsPoly.getSortedExponents(); rhsExponents is a list of integers. 49 for( Iterator it = rhsExponents.iterator(); it.hasNext(); ) The iterator() method returns an Iterator object with methods next() and hasNext(). hasNext() terminates the for loop when the iteration is done, 51 Integer key = it.next(); and next() returns the next integer in the set of exponents. ## class AddablePolynomial(Polynomial, Addable): def __add__(self, poly2): '''Add to self the elements of poly2, creating new elements if necessary, just adding coefficients where possible. Return a new polynomial, leaving the original polynomials unaltered. Treat an AddableInteger as a special type of Polynomial. If poly2 is anything but a Polynomial or AddableInteger, return None. >>> print apoly1; print poly2 0.3x^55 + 1.2x^4 - 3.1 1.7x^55 - 2.1x^3 + 4.2 >>> print apoly1 + poly2 # add a Polynomial 2.0x^55 + 1.2x^4 - 2.1x^3 + 1.1 >>> print apoly1 + ai1 # add an AddableInteger 0.3x^55 + 1.2x^4 - 2.1 >>> print apoly1 + 1 # add a normal integer None ''' # Build a dict with values to be added polyDict2 = {} # {55: 1.7, 3: -2.1, 0: 4.2} if isinstance(poly2, Polynomial): for exp in poly2._getSortedExponents(): # [55, 3, 0] polyDict2[exp] = poly2.getCoefficientByExponent(exp) elif isinstance(poly2, AddableInteger): polyDict2[0] = poly2.getInteger().intValue() else: return None # signal for an invalid type of poly2 # Make a clone of the original object clone = copy.deepcopy(self) # Add the new values to the clone for exp in polyDict2: # [2] addVal = polyDict2[exp] oldC = self.getCoefficientByExponent(exp) newC = oldC + addVal clone.setCoefficientByExponent(exp, newC) return clone # for-loop more like original in Java (if you need to do something special # with the iterator): iterator = polyDict2.iterkeys() for exp in iterator: addVal = polyDict2[exp] oldC = self.getCoefficientByExponent(exp) newC = oldC + addVal newPoly.setCoefficientByExponent(exp, newC)