Object-oriented programming in Jython
Object-oriented programming (OOP) represents the state-of-the-art in software programming technique. OOP is based on the notion of creating a model (or simulation) of the target problem in your programs. Properly using OOP techniques reduces programming errors, speeds up software development, and facilitates the reuse of existing code. Jython fully supports the concepts and practice of OOP.
In the following sections I will introduce OOP and describe how it is achieved in Jython. In the next section I will discuss some of the more advanced features of object-oriented programming in Jython.
Jython is an object-oriented language that completely supports object-oriented programming. Objects defined by Jython have the following features:
Identity: Each object must be distinct and
this must be testable. Jython supports the
is nottests for this purpose.
State: Each object must be able to store state. Jython
provides attributes (a.k.a. fields or instance
variables) for this purpose.
- Behavior: Each object must be able to manipulate its state. Jython provides methods for this purpose.
Note that the
id(object) built-in function returns a
unique integer identity value. So, the expression
x is y is
id(x) == id(y).
In its support for object-oriented programming, Jython includes the following features:
Class-based object creation: Jython classes are
templates for the creation of objects. Objects are data
structures with associated behavior.
Inheritance with polymorphism: Jython supports
single- and multiple-inheritance. All Jython instance
methods are polymorphic (or virtual) and may be
overridden by subclasses.
- Encapsulation with data hiding: Jython allows (but does not require) attributes to be hidden, thus permitting access outside the class itself only through methods of the class. Classes implement functions (called methods) to modify the data.
Defining a class is a lot like defining a module in that both variables and functions can be defined. Unlike the Java language, Jython allows the definition of any number of public classes per source file (or module). Thus, a module in Jython is much like a package in the Java language.
We use the
class statement to define classes in
class statement has the following form:
class name ( superclasses ): statement -- or -- class name ( superclasses ): assignment : function :
When you define a class, you have the option to provide zero or more assignment statements. These create class attributes that are shared by all instances of the class. You can also provide zero or more function definitions. These create methods. The superclasses list is optional. We'll discuss superclasses a little later in the tutorial.
The class name should be unique in the same scope (module, function, or class). The class name is really a variable bound to the class body (similar to any other assignment). In fact, you can define multiple variables to reference the same class.
Classes are used to hold class (or shared) attributes or to create class instances. To create an instance of a class you call the class as if it were a function. There is no need to use a new operator like in C++ or the Java language. For example, with the class
class MyClass: pass
the following statement creates an instance:
x = MyClass()
In Jython (unlike in the Java language) clients can add fields (also known as attributes) to an instance. Only the one instance is changed. To add fields to an instance (x) just set new values on that instance, as shown below:
x.attr1 = 1 x.attr2 = 2 : x.attrN = n
Any variable bound in a class is a class attribute (or
variable). Any function defined within a class is a method.
Methods receive an instance of the class, conventionally called
self, as the first (perhaps only) argument. For example, to
define some class attributes and methods, you might enter:
class MyClass: attr1 = 10 # class attributes attr2 = "hello" def method1(self): print MyClass.attr1 # reference the class attribute def method2(self, p1, p2): print MyClass.attr2 # reference the class attribute def method3(self, text): self.text = text # instance attribute print text, self.text # print my argument and my attribute method4 = method3 # make an alias for method3
Note that inside a class, you should qualify all references to
class attributes with the class name (for example,
MyClass.attr1) and all references to instance attributes
self variable (for example,
Outside the class, you should qualify all references to class
attributes with the class name (for example,
an instance (for example,
x.attr1) and all references to
instance attributes with an instance (for example,
where x is an instance of the class).
To achieve data hiding, it is often desirable to create "private" variables, which can be accessed only by the class itself. Jython provides a naming convention that makes accessing attributes and methods outside the class difficult. If you declare names of the form: __xxx or __xxx_yyy (that's two leading underscores), the Jython parser will automatically mangle (that is, add the class name to) the declared name, in effect creating hidden variables. For example:
class MyClass: __attr = 10 # private class attribute def method1(self): pass def method2(self, p1, p2): pass def __privateMethod(self, text): self.__text = text # private attribute
Note that unlike C++ and the Java language, all references to instance
variables must be qualified with
self; there is
no implied use of
__init__ method serves the role of an instance
constructor. It is called whenever an instance is created. This
method should be defined for all classes. Method
may take arguments. In Jython, and unlike in C++ or the Java language, all instance variables (also known as attributes or fields) are created
dynamically by assignment. They should be defined (that is, assigned to)
__init__. This ensures they are defined for subsequent methods to use. Some examples are as follows:
class Class1: def __init__ (self): # no arguments self.data =  # set implicit data class Class2: def __init__ (self, v1, v2): # 2 required arguments self.v1 = v1 # set data from parameters self.v2 = v2 class Class3: def __init__ (self, values=None): # 1 optional argument if values is None: values =  self.values = values # set data from parameter
If you allocate any resources in the
(or any other method), you need to ensure they are released before
the object is deallocated. The best way to do this is by using the
__del__ method. The
__del__ method is called just
before the garbage collector deallocates the object. You should also
provide a cleanup method (typically named
dispose) that can be called
directly. Here's an example:
class Class: def __init__ (self, db): self.connection = db.getConnection() # establish a connection self.connection.open() def __del__ (self): # cleanup at death self.close() def close(self): # cleanup if not self.connection is None and self.connection.isOpen(): self.connection.close() # release connection self.connection = None
Classes can also be assigned to variables (including function arguments). This makes writing dynamic code based on classes quite easy, as you can see from the following generic class instance factory:
def instanceMaker(xclass, *args): return apply(xclass, args) : x = instanceMaker(MyClass) # same as: x = MyClass()
The ability to inherit from classes is a fundamental to object-oriented programming. Jython supports both single and multiple-inheritance. Single inheritance means there can be only one superclass; multiple inheritance means there can be more than one superclass.
Inheritance is implemented by subclassing other classes. These classes can be either other Jython classes or Java classes. Any number of pure-Jython classes or Java interfaces can be superclasses but only one Java class can be (directly or indirectly) inherited from. You are not required to supply a superclass.
Any attribute or method in a superclass is also in any subclass and may be used by the class itself or any client (assuming it is publicly visible). Any instance of a subclass can be used wherever an instance of the superclass can be used -- this is an example of polymorphism. These features enable reuse, rapid development, and ease of extension.
Below are some examples of inheritance:
class Class1: pass # no inheritance class Class2: pass class Class3(Class1): pass # single inheritance class Class4(Class3,Class2): pass # multiple inheritance from java import awt from java import io # inherit a Java class and interface and a Jython class class MyPanel(awt.Panel, io.Serializable, Class2): :
__init__ method of a subclass must call any
__init__ method defined for its superclass; this is not
automatic. The two examples below demonstrate how the
__init__ method can be used with inheritance.
class Class1(SuperClass): def __init__ (self): # no arguments SuperClass.__init__(self) # init my super-class self.data =  # set implicit data class Class2(SuperClass): def __init__ (self, v1, v2): # 2 required arguments SuperClass.__init__(self, v1) # init my super-class with v1 self.v2 = v2
And here are some examples of initializing with multiple inheritance:
class Class1(Super1, Super2): def __init__ (self): # no arguments Super1.__init__(self) # init each super-class Super2.__init__(self) self.data =  # set implicit data class Class2(Super1, Super2): def __init__ (self, v1, v2, v3): # 3 required arguments # note you may do work before calling the super __init__ methods self.v3 = v3 # set data from parameter Super1.__init__(self, v1) # init each super-class Super2.__init__(self, v2)
You can call any superclass method by qualifying it with the class name, as shown here:
class Class1: def method1 (self): : class Class2(Class1): def method1 (self): # override method1 : Class1.method1(self) # call my super-class method : def method2 (self): : class Class3(Class2): def method1 (self): # override method1 : Class2.method1(self) # call my super-class method : def method3 (self): :
Note that the secondary method definitions (in
Class3) override the superclass definitions. There is
no requirement that the subclass method call its superclass method;
however, if it doesn't, then it must completely replace the function
of the superclass method.
There are two syntaxes for calling methods (assuming you have
an instance of
MyClass referenced by variable
The first form typically is used in class client coding while the second one is used more often in subclasses to call superclass methods.