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
"This class contains info about a customer"
_saysText = " says: "
def __init__(self, name = "Christian"):
self._name = name
print "From within property getter"
def _setName(self, value):
print "From within property setter " + value
self._name = value
print "From within property delete"
Name = property(_getName, _setName, _delName)
def __getitem__(self, index):
def _Write(self, text):
print self.Name + self._saysText + text
def Say(self, 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:
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 + obj + obj
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.