CSC/ECE 517 Fall 2011/ch6 6b ra

From Expertiza_Wiki
Revision as of 20:36, 16 November 2011 by Rvijaya2 (talk | contribs)
Jump to navigation Jump to search

Subclassing


Introduction

Subclassing is one of the significant features of OO programming, which greatly increases the reusability of classes and also minimizes duplication of code. A subclass usually inherits some properties from a super class. Inheritance is a design principle in object oriented languages like Java. The reason behind inheritance is to reuse the code of existing objects or establish a subtype from an object. This greatly improves the efficiency and makes the code more readable as methods which are written only once can be used by a lot of subclasses. A superclass consists of common features that can be extended over subclasses. Superclass and subclass are commonly called base and derived class. The relationship between a subclass and superclass can be represented by a simple UML diagram as shown below.

Advantages of Subclassing

Method Overriding

This feature mainly depends on the object oriented language but it’s advantage can be exploited by using subclasses. It permits a class to replace the implementation of a method that has been inherited. This process is termed as overriding. Overriding requires the compiler to perform some sort of optimization so that the right method is invoked. C++ uses virtual pointer along with vatbles to remember which function has overridden it’s definition inherited from the base class. In C#, overriding of a method should be specified by the program itself. The following example illustrates method overriding in C++.

#include <iostream.h>

class Base {
public :
virtual void show() {
	cout << "In Base";
}
};

class Derived:public Base {
public :
void show() {
	cout << "In Derived";
}
};

void main() {
	Base b;
	Derived d;
	Base *b2 = new Derived();
	b.show();
	d.show();
	b2->show();
}

Reusability

By creating subclass, the code of the base class can be reused in many situations. This gives subclass the freedom to create more specialized functions. It can use the base class methods to create these special functions. Apart from avoiding code duplication, this helps in decreasing the file size thereby saving some memory space.
For instance, we maybe programming animal characteristics but there is a special class of animals called mammals. Mammals display some specialized functions which can be defined in the subclass. As per Liskov Substitution principle which is discussed later, mammals obey the constraints enforced by the animal class and hence this kind of implementation avoids code duplication.

Liskov Substitution Principle

The Liskov Substitution principle provides the principle for substitution in object oriented programming. This principle was formally introduced by Barbara Liskov in a 1987 conference keynote address entitled Data abstraction and hierarchy. The principle states that "If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T".

This precisely means that functions that use references to base (Super) classes must be able to use objects of derived (Sub) classes without knowing it[2].

LSP is an extension of the Open-Closed principle[3]. As we can tell by the name, what this principle seems to mean is that classes should be open for extension but closed for modification. The Open Closed Principle (OCP) is one of the most fundamental class category principle. So much so that, most of class principles have been derived fromOCP.

OCP allows the programmers to add new features to the system without resorting to modifications of preexisting classes. So, a new data structure can be added to the system without having to modify the existing system's legacy code base. By doing so, it provides a solid foundation for building code that could be maintainable as well as reusable. Achievement of OCP can be done by adhering to the basic principle of OCP i.e. reducing coupling between classes to the abstract level. This can be done by formulating relationships between a concrete class and an abstract class (For Java, an interface), instead of creating relationships between two concrete classes.

[1] To better understand how the OCP works, we need to know what mechanisms it is based on. These are: abstraction and polymorphism. With the use of inheritance we can create derived classes that conform to the abstract polymorphic interfaces defined by pure virtual functions in abstract base classes.

Looking back at the Liskov principle, it also states that 'Subclasses should be substitutable for their base classes'[3]. In order to take advantage of LSP, we must adhere to OCP because violations of LSP also are violations of OCP, but not vice versa. LSP and OCP almost seem to be the same albeit a subtle difference which is difficult to spot. OCP is centered around the concept of abstract coupling. LSP, while also heavily depending on abstract coupling, also draws heavily from the concept of preconditions and postconditions. This is LSP's relation to Design by Contract, where the concept of preconditions and postconditions were formalized.[3]

To further simplify the concept, we present the following definitions:

Precondition  : This is a condition that must be satisfied before a method can be invoked.

Postcondition  : This condition must be true upon method completion.

Thus, the agreement between the client that it will satisfy the precondition and the supplier will satisfy the post-condition is called as ‘Design by Contract’.


Implicilty, this means that if the precondition is not met, the method shouldn't be invoked, and if the postcondition is not met, the method shouldn't return. These conditions are sometimes difficult to be checked categorically as most of them are always based on some manual assertions or nonexecutable comments. Because of this, violations of LSP can be difficult to find. Next we would like to consider the design rules that govern this particular use of inheritance. Also, it would be worth considering the traps that cause hierarchies to be created that do not conform to the Open-Closed principle. This could be done to better understand the principle and the situations where it could prove to be very useful.

LSP Violation

Following is another definition of the LSP, with whose reference we explain the example given below: “Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.”

Suppose we have an Interface defined as follows

public interface IMessageBox
{
	void showOption();
	void saveChange();
}

This interface represents a message sending entity that displays and can also make changes to the messages setting options. Following are the mock implementations of the interface.

public class PhoneSettings : IMessageBox
{
	public void showOption()
{	//show some Message setting options for the phone
	}
public void saveChange()
{	// save the changes  to the Message settings options for the phone
	}
}

public class UserSettings : IMessageBox
{
	public void showOption()
{	//show some Message settings for the phone
	}
public void saveChange()
{	// save  the changes to the Message settings for the phone
	}
}

Suppose in our example we have a method to retrieve the list of all instances of the implementation of the interface.

static  IEnumerable<IMessageBox> ShowAll()
{
	var allOptions = new List<IMessageBox>
				{
					new PhoneSettings();
					new  UserSettings();
				} ;
	allOptions.ForEach(r => r.Show());
	return allOptions;
}

Conclusion

See also

External Links:

References: