Inheritance is a Smalltalk trait that enables a class to have the same behavior as another class and then change that behavior to provide unique behavior. Inheritance is especially important in that it give the Smalltalk language reusability and extensibility. An example of inheritance is when someone has a program and they want that program to perform more that one function. Inheritance allows the user to extend the existing program to do a required function. The following diagram shows an example of inheritance
Inheritance involves superclasses and subclasses. These classes are similiar in heirarchy to the idea of class, genus, and family classification in the animal kingdom. The heirarchy of inheritance is unlimited. This means that subclasses can have subclasses that can also have subclasses. The Person class in the figure shown below has instance variables called name, address, and phoneNumber. The subclass Customer has the same instance variables. The class Person supports the messages name, address, phoneNumber, name:, address:, and phoneNumber:. The subclass Customer also supports these messages. This is an excellent example of how a class inherits the methods and variables from its superclass.
In inheritance, the subclass always takes on the behavior of the superclasses above it. This behavior can be methods and variables. The following sections will be covered in this chapter. They are inheritance of methods, inheritance of variables, abstract classes, and super vs. self.
addPerson Creates a new instance of Person and adds it to the collection
In the above figure, the Customer class definition would also like to manage customer orders. Therefore, the class definiton would add :customer Orders,customerOrders:, and addCustomerOrder:. The customer class definition can now support all of the messages or methods in Person and the three new messages.
Overriding Methods
Overriding an inherited method is another tool users have in providing unique behaviors to a class. If an object receives a message that does have a method for that message in the class definition, the object works its way up the heirachy until it finds a method with that name. Inherited methods cannot be deleted, but there are times when the method of the superclass does not reflect the needs of the subclass. In this case, the subclass provides a method by the same name with no code in the method. This process simply replaces the behavior of the superclass behavior with no behavior.
The figure shown above depicts how Smalltalk works up the heirarchy when looking for the methods for a message.
Sending Methods to Instances
In the hierarchy, the instance methods of a subclass inherit the methods of its superclass. The instance method of a class can receive a message to look for a method that is not supported by that class. The instance method looks at itself to see if the method exists within itself. If not, the instance method looks at the superclass of the class and proceeds to the parent of its superclass. Once the method is found, it is then inherited into the instance of the subclass. This process explains how the instance method of a class can inherit the method of its superclass.
Inheritance of Variables
The hierarchy of the Smalltalk language is designed such that the subclasses inherit the variables of its superclass. Subclasses can also add variables of its own. Class and instance variables are added to the class by placing them in the class definition. Classes inherit instance variables differently than they inherit class variables.
Instance Variables
Instance variables are defined in the class definition. The instance methods are found in a class and its subclasses. Data for instance is held in a data area created by Smalltalk.
The variable Customer has instance variables name, address, phoneNumber, and customerOrders. These variables include those instance variables inherited from Person. Each instance has its own copy of an instance variable, therefore making the instance variable private to its own instance. Therefore, the variable name must start with a lowercase letter.
Class Variables
Class variables are defined in the class definition. The class methods are found in the class and its subclasses. The local class heirarchy has its own copy of a class variable. The local class and all its subclasses refer to that one variable, therefore making the class variable a shared variable. Sending the addPerson message to Person creates a new instance of the Person class and add it to the list of all instances. Persons, a class variable will point to this list of instances. The code to perform this function is shown below.
addPerson "Add a new person and store it in the collection. Return the new instance." ^self persons add: self newThe message self allows the receiving object to get the contents of the class variable Persons by sending the addPerson message to itself.
The above figure shows that the instance of Set pointing to Persons now contains a new instance of Person. The figure shows how an instance inherits the behavior of its superclass. The instance Set can also take on a new instance Customer by inheriting the behavior from the superclass Person.
Class variables allow common sharing of information across a range of subclasses. All shared variable names start with a capital letter.
Class Instance Variables
Class instance variables are defined in the class definition. The class instance methods are found in the defining class and its subclasses. Each class and its subclasses have a copy of this variable, therefore making the class instance variable private to the class. Sample code for accessing data from persons in the instance method is as follows:
persons "Return the contents of persons. Make sure this variable is initialized." persons isNil ifTrue: [persons := Set new]. ^personsClass instance variables allow inheritance of class behavior across the range of subclasses, but each subclass manages its own class state. It is important to note that class instance variables are isntance variables that define the state of the class rather that the instance of the state of the class.
Abstract Classes
Abstract classes provide behavior across a set of subclasses, but it will never have its own instances. There are two types of method that abstract classes provide. The first type provides a complete method that a subclass inherits. The second type provides a method interface that is common to all subclasses but contains no code. The figure shown below indicates the abstract classes as a shaded block.
The abstract classes: Collection, SequenceableCollection, AdditiveSequenceableCollection, and ArrayedCollection provide a common set of messages to their subclasses. Each sublcass provides its own code to override the skeleton method. This skeleton method is defined as the common protocol to all the subclasses but does not provide a common implementation.
Super vs. Self
The use of super causes the method search to begin with the superclass of the receiving object. Super is a unique way for the class to add behavior to the inherited methods and not just replace them. When super is encountered in the running of the program, Smalltalk looks for a matching method in the superclass of the receiver.
Super is also used to create instance variables for every new instance. This is done by providing an initialize method for each class. An example of creating a new instance of a class is
Private Class Methods new ^super new initializeSelf causes the method search to begin with the receiving object itself. When self is encountered in the running of the program, Smalltalk looks for a matching method in the receiver. An example of the use of the self command is self.calculate which means to send the calculate message to self.
Summary
We have discussed the following in this chapter: