CSC/ECE 517 Fall 2012/ch1b 1w46 sm: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
 
(20 intermediate revisions by the same user not shown)
Line 5: Line 5:


Subclassing is a principle of creating a specialization(subclass/ [http://msdn.microsoft.com/en-us/library/chsw0hdc.aspx]) of a [http://www.webopedia.com/TERM/B/base_class.html base class](superclass/ parent class) by inheriting the methods and instance data from the base class.
Subclassing is a principle of creating a specialization(subclass/ [http://msdn.microsoft.com/en-us/library/chsw0hdc.aspx]) of a [http://www.webopedia.com/TERM/B/base_class.html base class](superclass/ parent class) by inheriting the methods and instance data from the base class.
<p> Subclassing is one of the significant features of [http://en.wikipedia.org/wiki/Object-oriented_programming 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. [http://en.wikipedia.org/wiki/Inheritance 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.  
Subclassing is one of the significant features of [http://en.wikipedia.org/wiki/Object-oriented_programming 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. [http://en.wikipedia.org/wiki/Inheritance 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.  


<br>[[File:UML_Subclass.jpg]]
<br>[[File:UML_Subclass.jpg]]


=='''Advantages of Subclassing'''==
=='''Examples of Subclassing'''==
 
The following example illustrates method overriding in Java.
 
<pre>
public class Base{
  public String printName(){
   
    System.out.println("Base Class");
  }
}


===Method Overriding===
public class Child extends Base{
  public String printName(){
   
    System.out.println("Child Class");
  }
}


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 [http://en.wikipedia.org/wiki/Vtable vtables] 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++.
public class Test{
public static void main(String args[]){
  Base b = new Base();
  b.printName();  //prints "Base class"
  Child c = new Child();
  c. printName(); //prints "Child class"
  b = c;
  b.printName(); //prints "Child class"
}
}
</pre>
 
The following example illustrates subclassing in C++


<pre>
<pre>
Line 20: Line 47:
class Base {
class Base {
public :
public :
virtual void show() {
virtual void printName() {
cout << "In Base";
cout << "Base Class";
}
}
};
};


class Derived:public Base {
class Child:public Base {
public :
public :
void show() {
void printName() {
cout << "In Derived";
cout << "Child Class";
}
}
};
};
Line 34: Line 61:
void main() {
void main() {
Base b;
Base b;
Derived d;
Child c;
Base *b2 = new Derived();
Base *b2 = new Child();
b.show();
b.printName();
d.show();
c.printName();
b2->show();
b2->printName();
}
}
</pre>
</pre>
=='''Advantages of Subclassing'''==


===Reusability===
===Reusability===
Line 47: Line 78:
<br> 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.
<br> 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.


==Why do we Subclass?==
* Code reuse
* Specialization: A subclass can define new methods it's superclass does not handle.
* Method Overriding: An overridding method can either have minor modifications or be completely changed from its parent class' implementation.


===Polymorphism===


 
This allows multiple definitions for the same method depending on the object it is invoked on. Subclasses of a class can define their own unique behaviors and yet share some of the same functionality of the parent class.
==Is Subclassing same as Subtyping?==
For example,
 
<pre>
===Subtyping===
   public class Car{
A is said to be a type of B if A's specification is same as B's. Subtypes should satisfy the '''Liskov Substitution Principle(LSP)''' which states,
    public String getEngineType(){
 
      return "Basic"
  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.
 
In most programming languages,for example java, ruby, C++, subclassing does not essentially mean subtyping. For a class to be a subtype, the subclass must follow the Liskov Substitution Principle. However it is easy to override a method with a completely new implementation and with stronger constraints. This is not checked by the compiler and we can create subclasses which are not subtypes. This is considered a bad approach, one of the reasons being, an argument to a method may be declared of one class A, but the method may be called with an argument of some subclass B. If we do not know if B is a true subtype of A, then we cannot assume that the behavior guaranteed by A is actually guaranteed by B, and so we cannot reason locally about this method.
 
 
 
'''Subclass not Subtype'''
 
   class A {
    int x;
    int get_x()
    {  
      return x;
    }
    int sum(A a) { return x + a.x }
   }
   }


   class B {
   public class Mercedes extends Car{
    int y;
    public String getEngineType(){
    int get_y()
      return "Advanced"
    {
    }
      return y;
    }
    int sum(B b)  
    {  
      if(y > 0)
        return x + b.x + y + b.y;
      else
        return 0;
    }
   }
   }
 
 
'''Subtype'''
   public class BMW extends Car{
   class A {
    public String getEngineType(){
    int x;
      return "Moderate"
    int get_x()
    }
    {  
      return x;
    }
    int sum(A a) { return x + a.x }
   }
   }


   class B {
   public class Tester{
    int y;
    public static void main(String[] args){
    int get_y()
        Car c = new Car();  
    {
        c.getEngineType();// returns "Basic"
      return y;
        c = new Mercedes();
    }
        c.getEngineType();// returns "Advanced"
    int product(B b)  
        c = new BMW();
    {
        c.getEngineType();// returns "Moderate"
      return x * y * b.x * b.y;
    }
    }
   }
   }
==Four perspectives of Inheritance==
The four perspectives help in determining when to subclass
===Code Reuse===
Code reuse is the practice of using the same segment of code in multiple applications.
''''Is Code Reuse alone a sufficient reason to use Inheritance?''''
No It is not.
Consider the following example.
<pre>
class Automobile_Part
{
    String name;
    String manufacturer_name;
    int part_id;
   
    void setManufacturerName(String mname)
    {manufacterer_name=mname;
    }
   
    int getPartID()
    {return part_id;
    }
   
}
class Medicine extends Automobile_Part
{
    String cures_disease;
    String getDiseaseName()
    {
        return cures_disease;
    }
}
</pre>
</pre>
In the above example, even though we have used the same variable type, the actual method invocation at runtime invokes the appropriate object's method and not the method defined by the variables's type.


Here the Medicine class extends the Automobile_Part class in order to reuse the  attributes "name" and "manufacturer_name" and "setManufacturerName" method. But it also inherits the "getPartID" method which is not appropriate for the Medicine class.
=='''Disadvantages of Subclassing'''==
   
So Code Reuse is in itself not a sufficient reason for using inheritance.


So if one wants to only achieve code reuse ,they can do so using Composition rather than Inheritance.  
===Tight Coupling===
Inheritance causes tight coupling between base class and subclasses. We cannot freely modify one without modifying (or at least performing substantial testing to make sure it doesn't break existing functionality in the other) the other.


''''Then what is Inheritance for?''''
'''The fragile base class problem''': Base classes are considered to be fragile because we cannot make changes to it and be sure that it doesn't impact any of the sub-classes without testing all of them. Moreover, we also need to test the client code which makes use of the base class and sub-class objects to make sure there are no regression bugs. A simple change to a base class can leave the system inoperable.


Inheritance is the mechanism by which one can achieve categorization and it it also facilitates polymorphism. Inheritance is used to build a hierarchy of concepts separated in categories at different levels of abstraction.
'''Security problems''': If a new feature is added to the base class which is required by a subset of sub-classes, then by adding it, we might accidentally provide access to the other sub-classes which shouldn't have access to it. This problem might not be realized until a security breach has occurred and it can have disastrous consequences. Also, there is no easy way to fix this with sub-classing and an alternate method needs to be looked for providing this feature to the sub-classes, possibly, by implementing a particular interface.


===Using subclassing solely for code reuse===
If a class inherits another class solely for code reuse and it doesn't have a IS-A relationship with this parent, this can lead to bloated and quite possibly buggy code. It can lead to bloated code if the subclass only makes use of one method in the parent(a large class with numerous methods). It can lead to buggy code if the base class decides to change the signature or possibly delete the methods which it knows for sure that the subclasses won't need. This will cause problems for those subclasses which do not exhibit the IS-A relationship and are improperly added to the class hierarchy. This defeats the whole purpose of inheritance and thinking in terms of objects and hierarchies.


===Is-A Perspective===
===Multiple Inheritance Problem===
Now let us consider both "[http://en.wikipedia.org/wiki/Is-a is-a]" relationship and Code reuse perspectives.
When a subclass inherits from more than one parent and both parents have the same method signature, then a conflict arises when we invoke the method on the subclass object.


''''Is the combination of code reuse and the “is-a” relationship among the classes a sufficient reason for using subclassing?''''
<pre>
#include <iostream.h>


Consider the following example.
class Base1 {
<pre>
public :
class Bird
  void printName() {
{
cout << "Base1 Class";
  String name;
  String getName()
  {
      return name;
  }
  void fly()
  {
      ...
  }
  void altitude()
  {
      ...
  }
}
}
};


class Penguin extends Birds
class Base2 {
{
public :
  void fly()
  void printName() {
  {
cout << "Base2 Class";
      throw new Exception();
  }
 
  void altitude()
  {
    throw new Exception();
  } 
}
}
</pre>
};
Even though Penguin is a Bird and Penguin class re uses the code in Bird class ,it is not appropriate to use inheritance here because the behavior of the inherited code is being changed.


Consider the case where a user invokes the method "altitude" in the Penguin class .The "altitude" method in Penguin class when invoked instead of displaying the altitude at which the bird flies it throws an exception thereby confusing the user.Code is not considered elegant if the user of that code is surprised or confused by the behavior of that code.
class Child:public Base1, Base2 {


This violates the Principle of Least Astonishment
};


  If a client thinks he has a reference to an object of type A but actually has a reference to an object of subtype B,
void main() {
  there should be no surprises when he sends messages to the object.
Child *c = new Child();
        c->printName();
}


So according to Principle of Least Astonishment whenever a sub class inherits functionality from the Super class.The subclass is not allowed to change the existing behavior by over ridding the inherited methods.
</pre>
 
This also violates the Liskov Substitution Principle because both the "fly" and "altitude" methods of Penguin class doesn't do everything that "fly" and "altitude" methods of its parent class Bird does. 
 
Therefore the combination of code reuse and “is-a” relationship among the classes is not a sufficient reason for using subclassing.
 
 
 
===Public Interface Perspective/ Behavioral subtyping===
 
Classes are programmed to [http://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html interfaces] and interfaces might have an overlap in functionality. One interface(subinterface) can extend another(superinterface).
 
 
  interface B{
      void common_method1(B b);
  }
  interface A extends B,C{
      void common_method2(A a);
      void common_method3();
  }
  A a = …;
  A a1 = …;
  a.common_method1(a1); // Behavioral subtyping – Argument of type B is replaced by its
                                        // subtype A
 
 
Interface A includes methods from B and C and transitively above B and C. An interface is considered a type. When A does everything B does and more, A can replace B wherever it is used. This is called '''behavioral subtyping''', and A is a subtype of B. For behavioral subtyping, LSP has to be followed.
 
[http://cs.colby.edu/djskrien/ Dale Skrien], in his [http://search.barnesandnoble.com/Object-Oriented-Design-Using-Java/Dale-Skrien/e/9780072974164?cm_mmc=borders-_-sku-_-NA-_-NA&redir=borders book], suggests the following guideline for subclassing,
"If a class B models a role played by class A, especially a temporary role,then  B should not be a subclass of A. Instead objects of class B should have references to objects of class A."
 
An example why inheritance should not be applied when the public interfaces for concerned classes are same but the above guideline does not hold
 
  class Person{
  String name;
  ...
  ...
  }
 
  class Student extends Person{
  ...
  }
 
  class Employee extends Person{
  ...
  }
 
Here the student and employee classes inherit from Person. "Student" could be an "Employee". Since both student and Employee classes extend Person, they have the data fields of Person duplicated. A reference to a Person object would be a better option than inheritance.
 
===[http://www.cs.bu.edu/teaching/cpp/polymorphism/intro/ Polymorphism]===
 
If all occurences of class A could be substituted by class B then it's good to have class B subclass A to avoid code duplication and by this we follow the LSP principle.


==Conclusion==
In the above example, the method PrintName is invoked on a child object. But, a conflict arises as to which method of the two parents needs to be invoked


===Is Liskov Substitution Principle restrictive?===


It depends,
=='''Conclusion'''==
If the developer in solely interested in reusing the code rather than keeping the behaviour or semantics of the methods intact, then he can do so by using sub-classing .But one can also achieve [http://www.ibm.com/developerworks/java/tutorials/j-lessismore/section2.html code reuse] using [http://www.wi-inf.uni-duisburg-essen.de/MobisPortal/upload/JOOP00.pdf Delegation] and [ Composition] which are relatively difficult to implement when compared to inheritance .But it is a good practice not to violate LSP principle while subclassing as it is one of the most powerful OO design principles which leads to good OO design.Furthermore,it provides more clarity to the user about the behaviour of the inherited methods inside the sub classes.Violation of LSP principle leads to messing up of class hierarchies. Mess being that whenever a subclass instance was passed as parameter to any method, strange behavior would occur.
Subclassing provides an elegant way to capture the hierarchical relationship among classes and promotes code reuse by defining common behavior in the base class and only providing the variations in the subclasses. Code reuse should not be the only reason for subclassing and the subclass should satisfy IS-A relationship.


=='''References'''==
http://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html


But again, if the developer is solely interested in achieving code reuse and if he finds Liskov Substitution Principle to be too restrictive then he can achieve the same using alternative methodologies such as [http://en.wikipedia.org/wiki/Design_by_contract  Design By Contract](DBC). The idea of DBC is to specify that part of the behaviour which must remain unchanged (by means of assertions and suchlike). This leads to a more precise notion of subtype. When using Design by Contract, subclasses in an inheritance hierarchy are allowed to weaken preconditions (but not strengthen them) and strengthen postconditions and invariants (but not weaken them). These rules approximate behavioral subtyping.
http://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)


==References==
http://en.wikipedia.org/wiki/Polymorphism
[1] http://publib.boulder.ibm.com/infocenter/comphelp/v7v91/index.jsp?topic=%2Fcom.ibm.aix.cbl.doc%2Ftpoot30.htm


[2] http://courses.csail.mit.edu/6.170/old-www/2001-Spring/recitations/recitation4.html
http://en.wikipedia.org/wiki/Subclass_(computer_science)#Subclasses_and_superclasses


[3] http://en.wikipedia.org/wiki/Code_reuse
http://docs.oracle.com/html/E24396_01/jdo_overview_mapping_inher.html


[4] http://www.isase.us/wisr3/7.pdf
http://www.cs.princeton.edu/courses/archive/spr96/cs333/java/tutorial/java/javaOO/subclasses.html


[5] http://littletutorials.com/2008/06/23/inheritance-not-for-code-reuse/
http://en.wikipedia.org/wiki/Object-oriented_programming


[6] [http://dl.acm.org/citation.cfm?id=62141 Keynote address - data abstraction and hierarchy], Barbara Liskov, MIT Laboratory for Computer Science, Cambridge, Ma.
http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html?page=1


[7] http://c2.com/cgi/wiki?LiskovSubstitutionPrinciple
http://expertiza.csc.ncsu.edu/wiki/index.php/CSC/ECE_517_Fall_2011/ch6_6b_ss


[8] http://www.objectmentor.com/resources/articles/lsp.pdf
http://expertiza.csc.ncsu.edu/wiki/index.php/CSC/ECE_517_Fall_2011/ch6_6b_ra

Latest revision as of 00:11, 11 October 2012

Subclassing

Subclassing

Subclassing is a principle of creating a specialization(subclass/ [1]) of a base class(superclass/ parent class) by inheriting the methods and instance data from the base class. 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.


Examples of Subclassing

The following example illustrates method overriding in Java.

public class Base{
   public String printName(){
    
    System.out.println("Base Class");
  }
}

public class Child extends Base{
   public String printName(){
    
    System.out.println("Child Class");
  }
}

public class Test{
 public static void main(String args[]){
   Base b = new Base();
   b.printName();  //prints "Base class"
   Child c = new Child();
   c. printName(); //prints "Child class"
   b = c;
   b.printName(); //prints "Child class"
 }
}

The following example illustrates subclassing in C++

#include <iostream.h>

class Base {
public :
virtual void printName() {
	cout << "Base Class";
}
};

class Child:public Base {
public :
void printName() {
	cout << "Child Class";
}
};

void main() {
	Base b;
	Child c;
	Base *b2 = new Child();
	b.printName();
	c.printName();
	b2->printName();
}


Advantages of Subclassing

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.


Polymorphism

This allows multiple definitions for the same method depending on the object it is invoked on. Subclasses of a class can define their own unique behaviors and yet share some of the same functionality of the parent class. For example,

  public class Car{
     public String getEngineType(){
       return "Basic"
     }
  }

  public class Mercedes extends Car{
     public String getEngineType(){
       return "Advanced"
     }
  }
  
  public class BMW extends Car{
     public String getEngineType(){
       return "Moderate"
     }
  }

  public class Tester{
     public static void main(String[] args){
        Car c = new Car();    
        c.getEngineType();// returns "Basic"
        c = new Mercedes();
        c.getEngineType();// returns "Advanced"
        c = new BMW();
        c.getEngineType();// returns "Moderate"
     }
  }

In the above example, even though we have used the same variable type, the actual method invocation at runtime invokes the appropriate object's method and not the method defined by the variables's type.

Disadvantages of Subclassing

Tight Coupling

Inheritance causes tight coupling between base class and subclasses. We cannot freely modify one without modifying (or at least performing substantial testing to make sure it doesn't break existing functionality in the other) the other.

The fragile base class problem: Base classes are considered to be fragile because we cannot make changes to it and be sure that it doesn't impact any of the sub-classes without testing all of them. Moreover, we also need to test the client code which makes use of the base class and sub-class objects to make sure there are no regression bugs. A simple change to a base class can leave the system inoperable.

Security problems: If a new feature is added to the base class which is required by a subset of sub-classes, then by adding it, we might accidentally provide access to the other sub-classes which shouldn't have access to it. This problem might not be realized until a security breach has occurred and it can have disastrous consequences. Also, there is no easy way to fix this with sub-classing and an alternate method needs to be looked for providing this feature to the sub-classes, possibly, by implementing a particular interface.

Using subclassing solely for code reuse

If a class inherits another class solely for code reuse and it doesn't have a IS-A relationship with this parent, this can lead to bloated and quite possibly buggy code. It can lead to bloated code if the subclass only makes use of one method in the parent(a large class with numerous methods). It can lead to buggy code if the base class decides to change the signature or possibly delete the methods which it knows for sure that the subclasses won't need. This will cause problems for those subclasses which do not exhibit the IS-A relationship and are improperly added to the class hierarchy. This defeats the whole purpose of inheritance and thinking in terms of objects and hierarchies.

Multiple Inheritance Problem

When a subclass inherits from more than one parent and both parents have the same method signature, then a conflict arises when we invoke the method on the subclass object.

#include <iostream.h>

class Base1 {
public :
  void printName() {
	cout << "Base1 Class";
}
};

class Base2 {
public :
  void printName() {
	cout << "Base2 Class";
}
};

class Child:public Base1, Base2 {

};

void main() {
	
	Child *c = new Child();
        c->printName();
	
}

In the above example, the method PrintName is invoked on a child object. But, a conflict arises as to which method of the two parents needs to be invoked


Conclusion

Subclassing provides an elegant way to capture the hierarchical relationship among classes and promotes code reuse by defining common behavior in the base class and only providing the variations in the subclasses. Code reuse should not be the only reason for subclassing and the subclass should satisfy IS-A relationship.

References

http://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html

http://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)

http://en.wikipedia.org/wiki/Polymorphism

http://en.wikipedia.org/wiki/Subclass_(computer_science)#Subclasses_and_superclasses

http://docs.oracle.com/html/E24396_01/jdo_overview_mapping_inher.html

http://www.cs.princeton.edu/courses/archive/spr96/cs333/java/tutorial/java/javaOO/subclasses.html

http://en.wikipedia.org/wiki/Object-oriented_programming

http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html?page=1

http://expertiza.csc.ncsu.edu/wiki/index.php/CSC/ECE_517_Fall_2011/ch6_6b_ss

http://expertiza.csc.ncsu.edu/wiki/index.php/CSC/ECE_517_Fall_2011/ch6_6b_ra