Mywiki2
Subclassing
Subclassing is the concept of creating a specialization(subclass/ derived class) of a base class(superclass/ parent class) by inheriting the methods and instance data from the baseclass.
Why do we Subclass?
1. Code reuse 2. Specialization: A subclass can define new methods it's superclass does not handle. 3. Method Overriding: An overridding method can either have minor modifications or be completely changed from its parent class' implementation.
Is Subclassing same as Subtyping?
Subtyping
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 which states,
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 fewer constraints. This is not checked by the compiler and we can create subclasses which are not subtypes.
Subclassing
Declaring one class to be a subclass of another class there by allowing a
subclass to inherit the functionality from its super class is called
subclassing.
/* we can include here the 4 perspectives of inheritance and then mention
LP principle , principle of least astonishment and some other solid principles of inheritance like the The Open-Closed
Principle and The Single Responsibility Principle.
*/
Links for the solid principles... http://www.objectmentor.com/resources/articles/ocp.pdf http://www.objectmentor.com/resources/articles/srp.pdf
Subclassing in Java
Extends Keyword
The extends is a Java keyword, which is used in inheritance process of
Java. It specifies the superclass in a class declaration using extends
keyword.To inherit a class, you simply incorporate the definition of one
class into another by using the extends keyword.
public class A { int a; char b; void method1() { } } class B extends A //class B inherits the properties of class A { void method2() { } }
Abstract classes
Abstract classes in Java are used to declare common characteristics of
subclasses. An abstract class cannot be instantiated i.e an object of an
abstract class cannot be created. It can only be used as a superclass for
other classes that extend the abstract class. Abstract classes are declared
using the abstract keyword. Abstract classes are used to provide a template
or design for concrete subclasses down the inheritance tree.
An abstract class can contain fields that describe the characteristics and
methods that describe the actions that a class can perform. An abstract
class can include methods that contain no implementation. These are called
abstract methods.If a class has any abstract methods, whether declared or
inherited, the entire class must be declared abstract. Abstract methods are
used to provide a template for the classes that inherit the abstract
methods.
Abstract classes cannot be instantiated; they must be subclassed, and
actual implementations must be provided for the abstract methods. Any
implementation specified can, of course, be overridden by additional sub-
classes. An object must have an implementation for all of its methods. You
need to create a subclass that provides an implementation for the abstract
method.
abstract class A { void method1() { ... ... ... } abstract void method2(); } class B extends A { void method2() { ... ... } }
If the class B does not implement the method "method2" then even class B
has to be declared as an Abstract class.
Rules that should be followed before subclassing
Subclassing vs Subtyping
The Liskov Substitution Principle in class typed languages
The Liskov Substitution Principle is a way of ensuring that inheritance is
used correctly.
It states that, in a computer program, if S is a subtype of T, then
objects of type T may be replaced with objects of type S (i.e., objects of
type S may be substitutes for objects of type T) without altering any of
the desirable properties of that program (correctness, task performed,
etc.).
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 less formal terms, it says that if a client (program) expects objects of
one type to behave in a certain way, then it’s only okay to substitute
objects of another type if the same expectations are satisfied.
Consider the following example which satisfies the Liskov Substitution
Principle
class Bird {
String name; void fly() { ... } void altitude() { ... }
}
class Sparrow extends Birds {
}
Example which does not satisfy the Liskov Substitution Principle
class Bird {
String name; void fly() { ... } void altitude() { ... }
} class Penguin extends Birds {
void fly() { throw new Exception(); }
void altitude() { throw new Exception(); }
} If an override method does nothing or just throws an exception, then you’re
probably violating the LSP. Therefore,this does not satisfy the Liskov Substitution Principle though
penguin "is-a" bird.
/* This is a direct lift off so we need to paraphrase it*/
The Liskov Substitution Principle in duck typed languages In programming languages with duck typing (e.g. Ruby, Python, Smalltalk)
classes don’t really define types. There is no type checking when assigning
objects to variables or passing objects as method arguments. There is a
kind of type checking when a method is called. It is checked that the
method exists with a matching number of parameters. Since classes don’t define types, inheritance in duck typed languages has
nothing to do with the subtype relation or the LSP. In a way clients define interfaces in an implicit way. Let’s look at an
example: def my_method1(a) do
a.m1() a.m2() my_method2(a)
end
def my_method2(a) do
a.m3()
end Calling my_method1 with an object a will succeed if the object a provides
the three methods m1, m2 and m3. This is the implicit interface the object
a needs to implement. And with this implicit interface comes the clients
expectation about the behaviour of m1, m2 and m3. That’s just the same as
with the Java interface. If an object b provides m1, m2 and m3 but doesn’t
fit the expected behaviour, the LSP is violated.
The LSP isn’t tied to inheritance or class based typing. It applies to duck
types languages as well as to systems without inheritance. LSP is a concept
that applies to all kinds of polymorphism. Only if you don’t use
polymorphism of all you don’t need to care about the LSP.
References
http://courses.csail.mit.edu/6.170/old-www/2001-Spring/recitations/recitation4.html