A while ago I heard a podcast where it was discussed that some believe that languages like C#/java etc are actually not object oriented but that they are really oriented. This provoked my thinking quite a bit, since OOP was the corner stone during my education, and we wrote all code in Java.
As the discussion went on I ended up seeing their point – even though I (of course) would never admit that C# is not object oriented :) The key point is that everything in C# is based around classes because the language is statically typed around classes. In a language like IronPython it is actually possible to manipulate each object, add methods, fields etc.
Manipulating objects in this way is also known as monkey patching, and it is something I will look into in a later blogpost. Today I will start off with a basic example of how to write a class in IronPython.
The following piece of code shows a basic class with a private field, constructor, property and a public method:
from System import Console
class Customer(object):
"This class contains info about a customer"
#Private field
_saysText = " says: "
#Constructor
def __init__(self, name = "Christian"):
self._name = name
#Property
def _getName(self):
print "From within property getter"
return self._name
def _setName(self, value):
print "From within property setter " + value
self._name = value
def _delName(self):
print "From within property delete"
Name = property(_getName, _setName, _delName)
#Indexer
def __getitem__(self, index):
return self.Name[index]
#Private method
def _Write(self, text):
print self.Name + self._saysText + text
#Public method
def Say(self, text):
self._Write(text)
There are a few things that are worth noticing here. First of all you see that import statements explicitly state which classes are imported. A * can be used to import all classes, but this is seen as bad practice in IronPython.
Private is not a keyword in IronPython, but when a member is prefixed with an underscore (_) it is private by convention. The constructor and indexer is also named in a special way, which is what is know as magic methods. Magic methods are used instead of implementing interfaces like IComparable and for constructors, indexers and the like. Magic methods are easy to spot as they are pre- and postfixes with a double underscore. The constructor is defined with a default value for the name parameter, in the same way as you can use default in params in VB and in C# from vNext.
All methods start by taking a parameter called self. As you can probably guess, this is so it can access members located on itself – so it is used like “this” in C#, but here it is required to use it when accessing members from the object itself.
The biggest thing to notice is the way the property is constructed. Properties are quite special in IronPython compared to C#. Because the language is dynamic properties do not have to be declared up front, and this means that properties are only created when you want to do something when the property is actually called. Because this is the case there is also a delete part, which is called when the property is removed from the object.
Note that the class inherits object – this is required to use properties! This is no big issue though, because IronPython supports multiple inheritance.
When we have this in place we can use the class like you see here:
print Customer.__doc__
help(Customer)
obj = Customer(name = "Jens")
obj.Say("I'm the king of the world!")
obj.Name = "Hans"
obj.Say("I'm the king of the world!")
print obj[0] + obj[1] + obj[2]
del obj.Name
Console.ReadLine()
Functions and statements do not have to be contained within a class, so this can be written directly beneath the code above where we declared the class.
The first two likes show how you can access information about the class. The first line writes out the string that I put directly under the constructor – which is how documentation can be added and introspected directly in IronPython. The second like prints an overview of which members exist on the class, which is something you will use a lot to examine new classes as you work with them.
The rest should be pretty straight forward. A few things to note are that named parameters are used in the constructor, and that you could actually set and print any property on the object – name is only used here to illustrate that the code in the get/set/delete functions is run when the property is used.