Background
Languages are designed, just like programs
Someone decides what the language is for
Someone decides what features it's going to have
Can't really understand a language until you have seen at least two
Java and Python have more similarities than differences
But the differences help explain why each language is the way it is
Typing
Java uses strong typing
Type of each variable must be declared
Variable X of type T can only refer to instances of that type (or derived types)
Allows method overloading on argument type
Python uses untyped variables and typed values
Eliminates need for type declarations
But makes overloading on argument type impossible
Have to switch on type instead
Which is harder to extend
Primitive vs. Reference Types
Both languages distinguish between primitive types and reference types
Distinction made for performance reasons
Primitive types:
Simple data values (e.g. integer) without methods
Immutable
Cannot be referenced
Reference types:
Dynamically allocated and referenceable
Have methods
There Are Lots of Other Choices
In Smalltalk and Ruby, everything is a first-class object with methods
# A small Ruby example with an anonymous function
5.upto(10) { |i| print i, " " }
5 6 7 8 9 10
In C++, objects can be on the stack, or on the heap
If they're on the stack, they are automatically destroyed when the declaring method returns
Which opens up a ton of security holes
class C {
public C() {
x = 0;
}
public int x;
}
C * good() {
return new C();
}
C * bad() {
C onStack;
return &onStack;
}
int main(int argc, char * argv[]) {
C * g = good();
C * b = bad();
}
![[Objects on Stack]](../img/objmodel/callStack.png)
Adding Members to Python Objects
Python "objects" are really dictionaries
Well, sort of
The notation x.y means (something like) x["y"]
Can access this dictionary directly as x.__dict__
Can add new members/methods on the fly
Just as you do in a constructor
Very handy
But can easily yield unmaintainable code
class Pair:
def __init__(self, left, right):
self.left = left
self.right = right
p1 = Pair("a", "b")
print p1.__dict__
{'right': 'b', 'left': 'a'}
p1.middle = "hello"
print p1.middle
hello
print p1.__class__.__dict__
{'__module__': '__main__', '__doc__': None,
'__init__': <function __init__ at 0x00867FB8>}
Static vs. Dynamic Models
Java's object model is static
Methods are compiled to create blocks of code
Once loaded, code cannot be modified
New code cannot be generated on the fly
Except by writing text, compiling it, and loading result
Python's object model is dynamic
Code is compiled as they are seen
New methods can be loaded on top of old ones
Methods can be added to classes after they have been created
class C:
def __init__(self):
self.value = 0
def method(self, arg):
self.value += arg
def __str__(self):
return `self.value`
obj = C()
obj.method(5)
print obj
def func(self, arg):
self.value -= arg
C.func = func
obj.func(2)
print obj
5
3
Dynamic Evaluation
Every programming system turns text into instructions, then executes the instructions
In Java and C++, these operations are performed by two separate programs (compiler and runtime)
In Python, they are performed by the same program (the interpreter)
So why not compile, load, and execute code within a running program?
Allows programs to add new code to themselves
This is how import works
Allows users to enter commands on the fly
Opens up a ton of security holes
Using eval in Python
import sys
x = 1
y = 2
z = eval("x + y")
print z
3
line = sys.stdin.readline() # user enters "print x + y + z"
eval(line)
6
Inheritance
Java classes can extend one parent, and implement zero more interfaces
Python has no notion of an "interface"
Methods are looked up at runtime
So X and Y are interchangeable if their methods have the same names and number of arguments
No common ancestors required
Python classes can extend any number of parents
Multiple inheritance
class Divider:
def __init__(self, val):
self.div = val
def doDiv(self, input):
return input / self.div
class Multiplier:
def __init__(self, val):
self.mul = val
def doMul(self, input):
return input * self.mul
class Factor(Divider, Multiplier):
def __init__(self, d, m):
Divider.__init__(self, d)
Multiplier.__init__(self, m)
f = Factor(2, 5)
print f.doDiv(4)
print f.doMul(3)
2
15
Collision
Multiple inheritance obviously useful
But how to handle collisions?
Outlaw multiple inheritance
Require users to resolve collisions when declaring derived classes
Specify a search order
Any useful programming language contains a certain amount of grit
You can move it around, but you can't get rid of it
![[Multiple Inheritance]](../img/objmodel/collision.png)
A Universe of Choices
There are many other ways to implement inheritance
E.g. JavaScript has no classes
Add members and methods to one object
Then clone it to create new instances
A prototype-based language
Inheritance implemented by:
Cloning the parent
Adding/changing members and methods
Using the modified child as a new prototype
Generic Programming
C++ supports generic programming using templates
Java 1.5 will too
Don't specify types when defining classes
Instead, use type variables
Then instantiate that class by filling in those placeholders with actual types
Compiler can often do this automatically
Allows programmers to express patterns that cut across type hierarchies
E.g. swap, min, max, etc.
Generic Methods
class Example {
template<class T>
public static void swap(T a, T b) {
T tmp = a;
a = b;
b = tmp;
}
public static void main(String[] args) {
String[] x = new String{"X1", "X2"};
String[] y = new String{"Y3"};
swap(x, y);
List left = new ArrayList();
List right = new LinkedList();
swap(left, right);
}
}
Generic Classes
template<class TL, class TR>
class Pair {
public Pair(TL left, TR right) {
fLeft = left;
fRight = right;
}
public TL getLeft() {
return fLeft;
}
...etc...
protected TL fLeft;
protected TR fRight;
}
public static void main(String[] args) {
Pair<Integer, String> p1 = new Pair(123, "abc");
Pair<String, Float> p2 = new Pair("xyz", 25.2);
String s1 = p1.getLeft(); // fails to compile
String s2 = p2.getLeft(); // works
}
Conclusion
There is no such thing as "the best language"
C++ is faster than Java, but permits errors that Java doesn't
Multiple inheritance allows reuse, but complicates maintenance
But some are better than others
E.g. Python is more readable than Perl
Each one is a vehicle for expressing certain patterns
The patterns are what matters
$Id: objmodel.html,v 1.1.1.1 2004/01/04 05:02:31 reid Exp $