[go: up one dir, main page]

0% found this document useful (0 votes)
75 views7 pages

Abstarction and Interface

Inheritance allows classes to establish an "is-a" relationship, where a subclass inherits properties and behaviors from its parent class. Composition establishes a "has-a" relationship, where one class contains another as a property. The key difference is that inheritance extends an existing class, while composition uses existing classes as properties without extending them.

Uploaded by

sankulsybca
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
75 views7 pages

Abstarction and Interface

Inheritance allows classes to establish an "is-a" relationship, where a subclass inherits properties and behaviors from its parent class. Composition establishes a "has-a" relationship, where one class contains another as a property. The key difference is that inheritance extends an existing class, while composition uses existing classes as properties without extending them.

Uploaded by

sankulsybca
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 7

Java 15

The increased quality and reduced development time are the by-products of the key benefits discussed above.
If 90% of the new application consists of proven existing components then only the remaining 10% of the code
have to be tested from scratch.

Q 07: How do you express an ‘is a’ relationship and a ‘has a’ relationship or explain inheritance and composition? What
is the difference between composition and aggregation? DC
A 07: The ‘is a’ relationship is expressed with inheritance and ‘has a’ relationship is expressed with composition. Both
inheritance and composition allow you to place sub-objects inside your new class. Two of the main techniques for
code reuse are class inheritance and object composition.

Inheritance [ is a ] Vs Composition [ has a ]

Building is a is a [House is a Building] has a [House has a Bathroom]


class Building{ class House {
has a ....... Bathroom room = new Bathroom() ;
} ....
public void getTotMirrors(){
class House extends Building{ room.getNoMirrors();
Bathroom ......... ....
House
} }
}

Inheritance is uni-directional. For example House is a Building. But Building is not a House. Inheritance uses
extends key word. Composition: is used when House has a Bathroom. It is incorrect to say House is a
Bathroom. Composition simply means using instance variables that refer to other objects. The class House will
have an instance variable, which refers to a Bathroom object.

Which one to use? The guide is that inheritance should be only used when subclass ‘is a’ superclass.

ƒ Don’t use inheritance just to get code reuse. If there is no ‘is a’ relationship then use composition for code
reuse. Overuse of implementation inheritance (uses the “extends” key word) can break all the subclasses, if
the superclass is modified.

ƒ Do not use inheritance just to get polymorphism. If there is no ‘is a’ relationship and all you want is
polymorphism then use interface inheritance with composition, which gives you code reuse (Refer Q8 in
Java section for interface inheritance).

What is the difference between aggregation and composition?


Aggregation Composition
Aggregation is an association in which one class Composition is an association in which one class belongs to a
belongs to a collection. This is a part of a whole collection. This is a part of a whole relationship where a part
relationship where a part can exist without a whole. cannot exist without a whole. If a whole is deleted then all parts are
For example a line item is a whole and product is a deleted. For example An order is a whole and line items are parts.
part. If a line item is deleted then corresponding If an order deleted then all corresponding line items for that order
product need not be deleted. So aggregation has a should be deleted. So composition has a stronger relationship.
weaker relationship.

Q 08: What do you mean by polymorphism, inheritance, encapsulation, and dynamic binding? DC
A 08: Polymorphism – means the ability of a single variable of a given type to be used to reference objects of different
types, and automatically call the method that is specific to the type of object the variable references. In a nutshell,
polymorphism is a bottom-up method call. The benefit of polymorphism is that it is very easy to add new classes
of derived objects without breaking the calling code (i.e. getTotArea() in the sample code shown below) that
uses the polymorphic classes or interfaces. When you send a message to an object even though you don’t know
what specific type it is, and the right thing happens, that’s called polymorphism. The process used by object-
oriented programming languages to implement polymorphism is called dynamic binding. Let us look at some
sample code to demonstrate polymorphism: CO
16 Java

Sample code:
//client or calling code <<abstract>>
For example: given a base Shape
double dim = 5.0; //ie 5 meters radius or width
List listShapes = new ArrayList(20); class/interface Shape,
polymorphism allows the +area() : double
Shape s = new Circle(); programmer to define
listShapes.add(s); //add circle
different area(double
s = new Square(); dim1) methods for any Circle
listShapes.add(s); //add square number of derived classes Square
such as Circle, Square etc. +area() : double
getTotArea (listShapes,dim); //returns 78.5+25.0=103.5
No matter what shape an +area() : double

//Later on, if you decide to add a half circle then define object is, applying the area
//a HalfCircle class, which extends Circle and then provide an method to it will return the HalfCircle
//area(). method but your called method getTotArea(...) remains right results.
//same.
+area() : double
s = new HalfCircle(); Later on HalfCicle can be
listShapes.add(s); //add HalfCircle added without breaking
your called code i.e.
getTotArea (listShapes,dim); //returns 78.5+25.0+39.25=142.75
method getTotalArea(...) «interface»
Shape
/** called method: method which adds up areas of various
+area() : double
** shapes supplied to it.
**/ Depending on what the
public double getTotArea(List listShapes, double dim){ shape is, appropriate
Iterator it = listShapes.iterator(); area(double dim) method Circle Square
double totalArea = 0.0; gets called and calculated.
//loop through different shapes
Circle Æ area is 78.5sqm +area() : double +area() : double
while(it.hasNext()) {
Shape s = (Shape) it.next(); Square Æ area is 25sqm
totalArea += s.area(dim); //polymorphic method call HalfCircle Æ area is 39.25
HalfCircle
} sqm
return totalArea ;
} +area() : double

Inheritance – is the inclusion of behaviour (i.e. methods) and state (i.e. variables) of a base class in a derived
class so that they are accessible in that derived class. The key benefit of Inheritance is that it provides the formal
mechanism for code reuse. Any shared piece of business logic can be moved from the derived class into the
base class as part of refactoring process to improve maintainability of your code by avoiding code duplication. The
existing class is called the superclass and the derived class is called the subclass. Inheritance can also be
defined as the process whereby one object acquires characteristics from one or more other objects the same way
children acquire characteristics from their parents.

There are two types of inheritances:

1. Implementation inheritance (aka class inheritance): You can extend an applications’ functionality by reusing
functionality in the parent class by inheriting all or some of the operations already implemented. In Java, you can
only inherit from one superclass. Implementation inheritance promotes reusability but improper use of class
inheritance can cause programming nightmares by breaking encapsulation and making future changes a problem.
With implementation inheritance, the subclass becomes tightly coupled with the superclass. This will make the
design fragile because if you want to change the superclass, you must know all the details of the subclasses to
avoid breaking them. So when using implementation inheritance, make sure that the subclasses depend only
on the behaviour of the superclass, not on the actual implementation. For example in the above diagram the
subclasses should only be concerned about the behaviour known as area() but not how it is implemented.

2. Interface inheritance (aka type inheritance): This is also known as subtyping. Interfaces provide a mechanism
for specifying a relationship between otherwise unrelated classes, typically by specifying a set of common
methods each implementing class must contain. Interface inheritance promotes the design concept of program to
interfaces not to implementations. This also reduces the coupling or implementation dependencies between
systems. In Java, you can implement any number of interfaces. This is more flexible than implementation
inheritance because it won’t lock you into specific implementations which make subclasses difficult to maintain. So
care should be taken not to break the implementing classes by modifying the interfaces.

Which one to use? Prefer interface inheritance to implementation inheritance because it promotes the design
concept of coding to an interface and reduces coupling. Interface inheritance can achieve code reuse with the
help of object composition. If you look at Gang of Four (GoF) design patterns, you can see that it favours
interface inheritance to implementation inheritance. CO
Java 17

Implementation inheritance Interface inheritance


Let’s assume that savings account and term deposit Let’s look at an interface inheritance code sample, which makes
account have a similar behaviour in terms of depositing use of composition for reusability. In the following example the
and withdrawing money, so we will get the super class to methods deposit(…) and withdraw(…) share the same piece of code
implement this behaviour and get the subclasses to reuse in AccountHelper class. The method calculateInterest(…) has its
this behaviour. But saving account and term deposit specific implementation in its own class.
account have specific behaviour in calculating the interest.
public interface Account {
public abstract class Account { public abstract void deposit(double amount);
public abstract void withdraw(double amount);
public void deposit(double amount) { public abstract int getAccountType();
//deposit logic }
}
public interface SavingsAccount extends Account{
public void withdraw(double amount) { public abstract double calculateInterest(double amount);
//withdraw logic }
}
public interface TermDepositAccount extends Account{
public abstract double calculateInterest(double amount); public abstract double calculateInterest(double amount);
}
}
The classes SavingsAccountImpl, TermDepositAccountImpl
public class SavingsAccount extends Account { should implement the methods declared in its interfaces. The class
AccountHelper implements the methods deposit(…) and
public double calculateInterest(double amount) { withdraw(…)
//calculate interest for SavingsAccount
} public class SavingsAccountImpl implements SavingsAccount{
} private int accountType = 1;

public class TermDepositAccount extends Account { //helper class which promotes code reuse through composition
AccountHelper helper = new AccountHelper();
public double calculateInterest(double amount) {
//calculate interest for TermDeposit public void deposit(double amount) {
} helper.deposit(amount, getAccountType());
} }
public void withdraw(double amount) {
The calling code can be defined as follows for illustration helper.withdraw(amount, getAccountType());
purpose only: }
public double calculateInterest(double amount) {
public class Test { //calculate interest for SavingsAccount
public static void main(String[] args) { }
Account acc1 = new SavingsAccount(); public int getAccountType(){
acc1.deposit(5.0); return accountType;
acc1.withdraw(2.0); }
}
Account acc2 = new TermDepositAccount();
acc2.deposit(10.0); public class TermDepositAccountImpl implements
acc2.withdraw(3.0); TermDepositAccount {
private int accountType = 2;
acc1.calculateInterest(500.00);
acc2.calculateInterest(500.00); //helper class which promotes code reuse through composition
} AccountHelper helper = new AccountHelper();
}
public void deposit(double amount) {
helper.deposit(amount, getAccountType());
}
public void withdraw(double amount) {
helper.withdraw(amount, getAccountType());
}
public double calculateInterest(double amount) {
//calculate interest for TermDeposit
}
public int getAccountType() {
return accountType;
}
}

The calling code can be defined as follows for illustration purpose


only:

public class Test {


public static void main(String[] args) {
18 Java

Account acc1 = new SavingsAccountImpl();


acc1.deposit(5.0);

Account acc2 = new TermDepositAccountImpl();


acc2.deposit(10.0);

if (acc1.getAccountType() == 1) {
((SavingsAccount) acc1).calculateInterest(500.00);
}

if (acc2.getAccountType() == 2) {
((TermDepositAccount) acc2).calculateInterest(500.00);
}
}
}

Encapsulation – refers to keeping all the related members (variables and methods) together in an object.
Specifying members as private can hide the variables and methods. Objects should hide their inner workings from
the outside view. Good encapsulation improves code modularity by preventing objects interacting with
each other in an unexpected way, which in turn makes future development and refactoring efforts easy.

Being able to encapsulate members of a class is important for security and integrity. We can protect variables
from unacceptable values. The sample code below describes how encapsulation can be used to protect the
MyMarks object from having negative values. Any modification to member variable “vmarks” can only be carried
out through the setter method setMarks(int mark). This prevents the object “MyMarks” from having any negative
values by throwing an exception. CO
Sample code
Class MyMarks {
private int vmarks = 0; k) in
private String name; ar tg Member
t m et
in M variables are
ks( ar encapsulated,
public void setMarks(int mark) ar ks
throws MarkException { tM () so that they
se
if(mark > 0) can only be
this.vmarks = mark; accessed via
else { private int vmarks; encapsulating
throw new MarkException("No negative private String name; methods.
Values");
} se
tN )
} am e(
e am
(S tN
tri
public int getMarks(){ ng ge
g
return vmarks; na rin
} m
e) St
//getters and setters for attribute name goes here.
}

Q 09: What is design by contract? Explain the assertion construct? DC


A 09: Design by contract specifies the obligations of a calling-method and called-method to each other. Design by
contract is a valuable technique, which should be used to build well-defined interfaces. The strength of this
programming methodology is that it gets the programmer to think clearly about what a function does, what pre
and post conditions it must adhere to and also it provides documentation for the caller. Java uses the assert
statement to implement pre- and post-conditions. Java’s exceptions handling also support design by contract
especially checked exceptions (Refer Q34 in Java section for checked exceptions). In design by contract in
addition to specifying programming code to carrying out intended operations of a method the programmer also
specifies:

1. Preconditions – This is the part of the contract the calling-method must agree to. Preconditions specify the
conditions that must be true before a called method can execute. Preconditions involve the system state and the
arguments passed into the method at the time of its invocation. If a precondition fails then there is a bug in the
calling-method or calling software component.
Java 19

On public methods On non-public methods


Preconditions on public methods are enforced by explicit checks You can use assertion to check the parameters of the
that throw particular, specified exceptions. You should not use non-public methods.
assertion to check the parameters of the public methods but
can use for the non-public methods. Assert is inappropriate private void setCalculatedRate(int rate) {
because the method guarantees that it will always enforce the assert (rate > 0 && rate < MAX_RATE) : rate;
argument checks. It must check its arguments whether or not //calculate the rate and set it.
assertions are enabled. Further, assert construct does not throw }
an exception of a specified type. It can throw only an
AssertionError. Assertions can be disabled, so programs must not
assume that assert construct will be always executed:
public void setRate(int rate) {
if(rate <= 0 || rate > MAX_RATE){ //Wrong: if assertion is disabled, CarpenterJob never
throw new IllegalArgumentException(“Invalid rate Æ ” + rate); //Get removed
} assert jobsAd.remove(PilotJob);
setCalculatedRate(rate);
} //Correct:
boolean pilotJobRemoved = jobsAd.remove(PilotJob);
assert pilotJobRemoved;

2. Postconditions – This is the part of the contract the called-method agrees to. What must be true after a
method completes successfully. Postconditions can be used with assertions in both public and non-public
methods. The postconditions involve the old system state, the new system state, the method arguments and the
method’s return value. If a postcondition fails then there is a bug in the called-method or called software
component.

public double calcRate(int rate) {


if(rate <= 0 || rate > MAX_RATE){
throw new IllegalArgumentException(“Invalid rate !!! ”);
}

//logic to calculate the rate and set it goes here

assert this.evaluate(result) < 0 : this; //this Æ message sent to AssertionError on failure


return result;
}

3. Class invariants - what must be true about each instance of a class? A class invariant as an internal invariant
that can specify the relationships among multiple attributes, and should be true before and after any method
completes. If an invariant fails then there could be a bug in either calling-method or called-method. There is
no particular mechanism for checking invariants but it is convenient to combine all the expressions required for
checking invariants into a single internal method that can be called by assertions. For example if you have a class,
which deals with negative integers then you define the isNegative() convenient internal method:

class NegativeInteger {
Integer value = new Integer (-1); //invariant

//constructor
public NegativeInteger(Integer int) {
//constructor logic goes here
assert isNegative();
}

//rest of the public and non-public methods goes here. public methods should call assert isNegative(); prior to its return

//convenient internal method for checking invariants. Returns true if the integer value is negative
private boolean isNegative(){
return value.intValue() < 0 ;
}
}

The isNegative() method should be true before and after any method completes, each public method and
constructor should contain the following assert statement immediately prior to its return.

assert isNegative();

Explain the assertion construct? The assertion statements have two forms as shown below:

assert Expression1;
20 Java

assert Expression1 : Expression2;

Where:

ƒ Expression1 Æ is a boolean expression. If the Expression1 evaluates to false, it throws an AssertionError without any
detailed message.
ƒ Expression2 Æ if the Expression1 evaluates to false throws an AssertionError with using the value of the Expression2 as
the errors’ detailed message.

Note: If you are using assertions (available from JDK1.4 onwards), you should supply the JVM argument to
enable it by package name or class name.

Java -ea[:packagename...|:classname] or Java -enableassertions[:packagename...|:classname]


Java –ea:Account

Q 10: What is the difference between an abstract class and an interface and when should you use them? LF DP DC
A 10: In design, you want the base class to present only an interface for its derived classes. This means, you don’t want
anyone to actually instantiate an object of the base class. You only want to upcast to it (implicit upcasting, which
gives you polymorphic behaviour), so that its interface can be used. This is accomplished by making that class
abstract using the abstract keyword. If anyone tries to make an object of an abstract class, the compiler prevents
it.

The interface keyword takes this concept of an abstract class a step further by preventing any method or function
implementation at all. You can only declare a method or function but not provide the implementation. The class,
which is implementing the interface, should provide the actual implementation. The interface is a very useful and
commonly used aspect in OO design, as it provides the separation of interface and implementation and
enables you to:

ƒ Capture similarities among unrelated classes without artificially forcing a class relationship.
ƒ Declare methods that one or more classes are expected to implement.
ƒ Reveal an object's programming interface without revealing its actual implementation.
ƒ Model multiple interface inheritance in Java, which provides some of the benefits of full on multiple
inheritances, a feature that some object-oriented languages support that allow a class to have more than one
superclass.

Diam ond problem & use of interface

Shape <<Interface>>
ShapeIF

C ircle Square C ircleO nSquare


C ircle Square

<<Interface>> <<Interface>>
C ircleIF SquareIF
C ircleO nSquare
M ultiple interface inheritance in JA VA
N o m ultiple inheritance in JA VA

Abstract class Interface


Have executable methods and abstract methods. Have no implementation code. All methods are abstract.

Can only subclass one abstract class. A class can implement any number of interfaces.

Can have instance variables, constructors and any Cannot have instance variables, constructors and can have
visibility: public, private, protected, none (aka package). only public and none (aka package) visibility.

When to use an abstract class?: In case where you want to use implementation inheritance then it is usually
provided by an abstract base class. Abstract classes are excellent candidates inside of application frameworks.
Abstract classes let you define some default behaviour and force subclasses to provide any specific behaviour.
Care should be taken not to overuse implementation inheritance as discussed in Q8 in Java section.
Java 21

When to use an interface?: For polymorphic interface inheritance, where the client wants to only deal with a type
and does not care about the actual implementation use interfaces. If you need to change your design frequently,
you should prefer using interface to abstract. CO Coding to an interface reduces coupling and interface
inheritance can achieve code reuse with the help of object composition. Another justification for using interfaces
is that they solve the ‘diamond problem’ of traditional multiple inheritance as shown in the figure. Java does not
support multiple inheritances. Java only supports multiple interface inheritance. Interface will solve all the
ambiguities caused by this ‘diamond problem’.

Design pattern: Strategy design pattern lets you swap new algorithms and processes into your program without
altering the objects that use them. Strategy design pattern: Refer Q11 in How would you go about… section.

Q 11: Why there are some interfaces with no defined methods (i.e. marker interfaces) in Java? LF
A 11: The interfaces with no defined methods act like markers. They just tell the compiler that the objects of the classes
implementing the interfaces with no defined methods need to be treated differently. Example Serializable (Refer
Q19 in Java section), Cloneable etc

Q 12: When is a method said to be overloaded and when is a method said to be overridden? LF CO
A 12:
Method Overloading Method Overriding
Overloading deals with multiple methods in the same class Overriding deals with two methods, one in the parent class and
with the same name but different method signatures. the other one in the child class and has the same name and
signatures.
class MyClass {
public void getInvestAmount(int rate) {…} class BaseClass{
public void getInvestAmount(int rate) {…}
public void getInvestAmount(int rate, long principal) }
{ … }
} class MyClass extends BaseClass {
public void getInvestAmount(int rate) { …}
Both the above methods have the same method names }
but different method signatures, which mean the methods
are overloaded. Both the above methods have the same method names and
the signatures but the method in the subclass MyClass
overrides the method in the superclass BaseClass.

Overloading lets you define the same operation in Overriding lets you define the same operation in different
different ways for different data. ways for different object types.

Q 13: What is the main difference between an ArrayList and a Vector? What is the main difference between Hashmap
and Hashtable? LF DC PI CI
A 13:
Vector / Hashtable ArrayList / Hashmap
Original classes before the introduction of Collections So if you don’t need a thread safe collection, use the ArrayList or
API. Vector & Hashtable are synchronized. Any Hashmap. Why pay the price of synchronization unnecessarily at
method that touches their contents is thread-safe. the expense of performance degradation.

So which is better? As a general rule, prefer ArrayList/Hashmap to Vector/Hashtable. If your application is a


multithreaded application and at least one of the threads either adds or deletes an entry into the collection
then use new Java collection API‘s external synchronization facility as shown below to temporarily synchronize
your collections as needed: CO

Map myMap = Collections.synchronizedMap (myMap);


List myList = Collections.synchronizedList (myList);

Java arrays are even faster than using an ArrayList/Vector and perhaps therefore may be preferable.
ArrayList/Vector internally uses an array with some convenient methods like add(..), remove(…) etc.

Q 14: Explain the Java Collection framework? LF DP

You might also like