Base classes in OOP programming languages


David Otton posted a short but thought-provoking post about stdClass, which many think is the “base class” all PHP classes automatically inherit from. I have to admit that I had this misconception as well.

On the other hand, “true” OOP languages such as C# and Java both have a base class which all other classes inherit, even if you don’t explicitly define it. They also tend to have somewhat deeper inheritance chains, as James Titcumb points out, in reply to David’s post.

This presents some room for analysis in how things are handled in dynamic and static languages, and how those differences affect things…

There are both static and dynamic typed languages which have a base class: Python and PHP don’t, but Ruby does. C# and Java do, but C++ doesn’t.

The main difference caused by this is the fact that objects in base-classed languages always have certain methods in them. For example, C# objects have Equals and GetType, amongst some others. These can be then extended in derived classes to provide more functionality, for example for easy comparison of objects to each other.

While PHP objects do not have an actual base class, they still come with certain methods – in PHP terminology, magic methods. They probably wouldn’t be magic if they were inherited from a base-class… Anyway, these methods, such as __toString, are somewhat similar to their non-magic counterparts in other languages.

Python also has a certain flavor of its own: While its classes won’t inherit from anything by default, it does have a built in class called object, which is the most base type in the language. I don’t know how common practice it is to inherit object, but at least by a quick look, most Python built in classes would appear to inherit it. As an interesting side note, functions in Python appear to have many of the same properties as object’s. However, a Python function is not a class.

The advantages of having a base-class aren’t immediately obvious, but it does have one: The fact that all classes share at least something, though this is mostly a case in static languages, as dynamic languages can use duck typing.

For example, every class in C# has the beforementioned ToString method, which you can use to output a textual representation of the object. Also, in static languages it has the added benefit of being able to create a generic list which can contain any kinds of objects. This is not as much an issue in dynamic languages, where lists can usually contain anything anyway.

You might now think that you can’t have a list of anything in C++, since the classes in C++ don’t have a base class. If you did, you would be wrong. C++ allows you to have “void pointers”, which essentially are pointers that can point to anything, so you could just create a list of void pointers.

There’s also the inheritance chain. It seems to me that in .NET many classes have deep inheritance chains, which isn’t always a good thing. For example, the System.Windows.Forms.Form class inherits ContainerControl, ScrollableControl, Control, Component, MarshalByRefObject and Object. Something like this is sometimes used as an example when talking about inheritance and composition: should a form inherit from “scrollable” or should the scrolling behavior be provided with composition (ie. a member Form.scroller or such). For the sake of comparison, a DataGrid component in PRADO also has a six classes deep inheritance chain.

One of the main problems with deep inheritance chains is that if you change one of the classes in the middle, you may unintentionally break something that would seem completely unrelated to the change you just did. I’ve been down that road myself, and it wasn’t easy to manage all that.

We could compare that to Zend Framework, where most components inherit from a single abstract base class. For example, you could create a datagrid using a view helper in ZF, and view helpers won’t even need to inherit a single class – just implement an interface. Granted, the complexity of a HTML datagrid is much smaller than a Windows form’s.

In “truely” object oriented languages, having a common base class is probably a good idea. It presents a common “starting point” and it probably clarifies things such as comparing objects and converting them into strings. For example, in PHP you probably wouldn’t know a magic method exists unless the manual stated so, but in some other language, the base object type would tell you what everything can do.