JavaScript Jems - The Inheritance Tax |
Written by Mike James | |||||
Tuesday, 09 April 2024 | |||||
Page 2 of 4
Hierarchical TypingThings are a little more complicated in most class-based languages in that they implement hierarchical type. In this case inheritance can be used to create a type hierarchy. For example: Class MyClassB:inherits MyClassA{ Now MyClassB has all of the properties of MyClassA plus whatever is added as part of its definition. MyClassB is said to be a subclass of MyClassA and, as it has all of the properties of MyClassA, you can use it anywhere you could use an instance of MyClassA. After all, typing is all about making sure that an object has the properties that you are using, and an instance of MyClassB has all of the properties of MyClassA and so it can be treated as such. MyClassB is also a subtype of MyClassA in the sense that it is also a MyClassA as well as being a new type all of its own. So it is perfectly OK in most strongly-typed, class-based languages to write things like: MyClassA myObject=new MyClassB(); and then proceed to use any properties that belong to MyClassA. This means that a variable can reference an object of its declared type or any subtype. If you make a mistake and try to use a property that MyClassA doesn't have, then the compiler will tell you about the error at compile time and you are saved a runtime error. Virtual InheritanceThere is a complication of this simple picture of inheritance. Suppose MyClassB overrides, that is redefines, a method to be more suitable for what it is doing. Now when you write: MyClassA myObject=new MyClassB(); myObject.myMethod(); which method is used - the one originally defined by MyClassA or the overridden version defined by MyClassB? In other words, is it the type of the variable which determines which method is called, or the type of the instance? There is no correct answer to this, but most languages will call the method determined by the instance not the variable. This is usually called virtual inheritance following C++ and in this case it would be the method defined in MyClassB that would be called. Interestingly C++ doesn't implement virtual inheritance by default and it would use the method defined in ClassA unless otherwise instructed. Of course, in JavaScript variables don't have type and so the method called always depends on the instance. Why Is Hierarchical Typing Useful?Hierarchical typing is useful because it allows you to write partially generic methods. Simple strong typing only lets a variable reference a particular class of instances and hence any function you write will only process that one single class of object. This is far too restrictive as usually you want your function to work with objects that are similar, but not necessarily identical. For example, suppose you have a class hierarchy Animal and two subclasses Cat and Dog. As long as you only want to use the methods and properties of Animal you can use hierarchical typing to write a method that can accept Animal as its parameter and use it with objects of type Animal, Cat or Dog. When you write a function that works with a type, it should also work with all of its subtypes. This is a consequence of the Liskov substitution principle which states that a subtype can always replace a type. However, this isn't always true. It is only true if we as programmers make it true. For example, it only works if we either don't override methods in subclasses or if we are careful to make sure that the overriding doesn't invalidate the substitution principle. It could be that we have created a new method in the subclass that simply doesn't work properly with the original class. Overriding methods potentially breaks the idea that you can use a subtype in place of the type and no amount of type checking is going to warn you of this. Most languages have a single topmost supertype that all other types derive from – usually called Object or something similar. You can use this to write completely generic methods because a variable of type Object can reference anything. However, because of strong typing the only methods that can be used are those that Object has, which are usually very few and very basic. Using the Object type you can write completely generic functions that work with any object. Of course, as JavaScript doesn't have typed variables, none of this is necessary and any function that works with an object will work with all objects as long as they have the properties that are used in the function. |
|||||
Last Updated ( Wednesday, 10 April 2024 ) |