Applying Inheritance to Solve problems
This presentation is the property of its rightful owner.
Sponsored Links
1 / 65

Applying Inheritance to Solve problems PowerPoint PPT Presentation


  • 64 Views
  • Uploaded on
  • Presentation posted in: General

Applying Inheritance to Solve problems. Classification, Generalization and Specialization. Classification the act of identifying and categorizing similar objects into classes is known as classification

Download Presentation

Applying Inheritance to Solve problems

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Applying inheritance to solve problems

Applying Inheritance to Solve problems


Classification generalization and specialization

Classification, Generalization and Specialization

  • Classification

    • the act of identifying and categorizing similar objects into classes is known as classification

    • the resulting categories are known as classes which form meaningful abstractions for organizing information

List of people objects in a furniture shop


Classification generalization and specialization1

Customer

- Alex

- Julia

- Chris

SalesPerson

Manager

Secretary

- Lawrence

- Peter

- John

- Anna

- Angela

Classification, Generalization and Specialization

People in Furniture Shop


Classification generalization and specialization2

SalesPerson

Manager

Secretary

- Lawrence

- Peter

- John

- Anna

- Angela

Classification, Generalization and Specialization

  • Generalization

    • generalization is the act of capturing similarities between classes and defining the similarities in a new generalized class

    • the original classes are known as subclasses, and the generalized class is known as superclass

Employee

superclass


Classification generalization and specialization3

Customer

- Alex

- Julia

- Chris

Classification, Generalization and Specialization

  • Specialization

    • specialization is the act of capturing differences among objects in a class and creating new distinct subclasses with the differences

PeopleInFS

Employee

subclass


Classification generalization and specialization4

Classification, Generalization and Specialization

  • Super- and sub-classes can be organized into a classhierarchy with the superclasses placed toward the top of the hierarchy and the subclasses toward the bottom of the hierarchy

  • which class an object is referred to in a class hierarchy is a matter of generality

superclass

PeopleInFS

superclass and

subclass

Customer

Employee

SalesPerson

Manager

Secretary

subclass


Inheritance example people in furniture shop

Inheritance Example: People in Furniture Shop

name

getName( )

PeopleInFS

name

address

budget

getName( )

getBudget( )

placeOrder( )

name

employeeNum

getName( )

getEmployeeNum()

Customer

Employee

name

employeeNum

commission

getName( )

getEmployeeNum( )

getCommission( )

takeOrder( )

SalesPerson

Manager

Secretary


Inheritance example people in furniture shop1

Inheritance Example: People in Furniture Shop

PeopleInFS

- name: String

+ getName( ): String

“inherits from ”

(or “is-a ”)

Customer

Employee

- address: String

- budget: int

+ getBudget( ): int

+ placeOrder( ): void

- employeeNum: int

+ getEmployeeNum( ): int

SalesPerson

Manager

Secretary

- commission: int

+ getCommission( ): int

takeOrder( ): int

- allowance: int

+ getAllowance( ): int


Applying inheritance to solve problems

Inheritance Example: People in Furniture Shop

SalesPerson

Employee

+ getCommission( ): int

+ takeOrder( ): int

PeopleInFS

+ getName( ): String

- name: String

+ getEmployeeNum( ): int

- employeeNum: int

- commission: int


Inheritance and java classes interfaces

Inheritance and Java Classes/Interfaces

subclass

or

derived class

superclass

or

base class

extends

extends

subinterface

superinterface

implements

class

interface


Applying inheritance to solve problems

Applied Inheritance

  • Decide on the classes involved from the problem description

    • Group classes into conceptually equivalent groups

    • Per group of classes, the generalizing concept will be a Parent to those classes

    • Distribute responsibilities amongst all classes based on what is appropriate and customary for that class

  • Example: A program to teach geometry needs to model some basic shapes

    • All shapes have surface area, could have volume and location

    • The shapes that need to be modeled are: Circle, Rectangle, Sphere, Cylinder, and a Square

  • What classes will you need?


Applying inheritance to solve problems

Shape

Shapes2D

Shapes3D

Circle

Rectangle

Sphere

Cylinder

Square

A Geometry Example

Classes: Circle, Rectangle, Sphere, Cylinder, Square, Coordinate

All “Shapes”

2D Shapes

Circle

Sphere

Coordinate

Rectangle

Group classes

Cylinder

Square

Square is a Rectangle

3D Shapes

Inheritance hierarchy


Applying inheritance to solve problems

Shape

Shapes2D

Shapes3D

Circle

Rectangle

Sphere

Cylinder

Square

A Geometry Example

Distribute Responsibilities:

Shape

+getSurfaceArea()

+clone()

+equals()

+toString()

+Object getLocation()

Shape3D

+getVolume()

Shape2D

+ ?

Is Shape2D needed?


Applying inheritance to solve problems

Example … Abstract classes

public abstract class Shape{

double getSurfaceArea();

Object getLocation();

Object clone();

String toString();

boolean equals();

}

Observe the syntax of Shape

The methods are not

virtual methods

Abstract Class: A class with at least one unimplemented method

Interface: A class with only unimplemented methods

.

public interface Shape{

double getSurfaceArea();

Object getLocation();

Object clone();

String toString();

boolean equals();

}


Applying inheritance to solve problems

Sample Interfaces

Q: How do you inherit from an interface?

A: By implementing the interface

public interface Shape implements Cloneable{

...

}

public abstract class Shape2D implements Shape{

...

}

Q: How do you inherit from an Abstract class?

A: The usual way, by extending

public class Circle extends Shape2D{

}


Applying inheritance to solve problems

Its All Still Inheritance!

public interface Shape extendsClonable{

}

public abstract class Shape2D implements Shape{

}

public class Circle extends Shape2D{

}

Circle has to implement all

unimplemented methods of

  • 2DShape

  • Shape

  • Clonable


Applying inheritance to solve problems

Its All Still Inheritance!

Client Code

Circle c = new Circle();

Shape s = c;

Cloneable cln = s;

Shape2D s2d = s;

Through c you can access ALL methods

of CircleAND its parents!

Through s you can access ONLY methods

of Shape and Cloneableimplemented in Circle

Through cln you can access ONLY methods

of Cloneable implemented in Circle

Through s2d you can access ONLY methods of Shape, Cloneable, and Shape2D implemented in Circle


Applying inheritance to solve problems

The Class Rectangle

public class Rectangle extends Shape2D{

private int width,length;

public Rectangle(int w,int l){

width = w;

length = l;

}

public int getSurfaceArea(){

return(width*length);

}


Applying inheritance to solve problems

The Class Rectangle

public boolean equals(Object o){

if(!o instanceOf Rectangle)

return false

Rectangle r = (Rectangle)o;

if (this.width != r.width)

return false;

if (this.length!=r.length)

return false;

return true;

}


Applying inheritance to solve problems

The Class Rectangle

public void toString(){

System.out.println(“Rectangle”+width+” “+length);

}

public Object clone(){

return(new Rectangle(width,length);

}

public Object getLocation(){

}


Applying inheritance to solve problems

The Class ShapePair

public abstract class ShapePair extends Shape{

private Shape shape1,shape2;

public ShapePair(Shape s1,Shape s2){

shape1 = s1;

shape2 = s2;

}

public int getSurfaceArea(){

return(shape1.getSurfaceArea() +shape2.getSurfaceArea());

}


Applying inheritance to solve problems

The Class Rectangle

public Object clone(){

Shape s1 = (Shape)shape1.clone();

Shape s2 = (Shape)shape2.clone();

return(new ShapePair(s1,s2);

}

  • A very simple example of grouping two shapes!


Understanding polymorphism

Understanding Polymorphism

  • Static vs dynamic binding

    • binding refers to the association of a method invocation and the code to be executed on behalf of the invocation

    • in static binding, all the associations are determined at compile time

      • conventional function calls are statically bound

        char shapeType[numShapes];

        struct circle circles[numCircles];

        struct square squares[numSquares];

        int c = 0, s = 0;

        ...

        for (i = 0; i < numShapes; i++)

        switch (shapeType[i]) {

        ‘c’: calculateCircleArea(circles[c++]); break;

        ‘s’: calculateSquareArea(squares[s++]); break;

        }


Understanding polymorphism1

Understanding Polymorphism

  • in dynamic binding, the code to be executed in response to a method invocation (i.e., a message) will not be determined until runtime

    • method invocations to variable shapeArray (in the following example) are dynamically bound

public class ShapeDemoClient {

public static void main(String argv[ ]) {

Circle c1 = new Circle("Circle C1");

Circle c2 = new Circle("Circle C2", 3.0f);

Square s1 = new Square("Square S1");

Square s2 = new Square("Square S2", 3.0f);

Shape shapeArray[ ] = {c1, s1, c2, s2};

for (int i = 0; i < shapeArray.length; i++) {

System.out.println("The area of " +

shapeArray[i].getName( ) + " is " +

shapeArray[i].calculateArea( ) + " sq. cm."); }

} // End main

} // End ShapeDemoClient1 class


Avoid confusion between is a and has a

Avoid Confusion Between Is-A and Has-A

  • Improper class hierarchies are commonly created when designers confuse is-a with has-a

    • “is-a” relation: the extension creates a new class that is kind of the original class, e.g,

    • “has-a” relation: an object of one class uses objects of other classes to store state or do work

    • A vehicle is-a Movable Abstraction

    • A vehicle is-a Physical Abstraction

    • A vehicle has-a location

    • A vehicle is-not-a Point (the class of location)

Rectangle

Square

1

*

circle

point


Composition versus inheritance

All aspects of the protocol are part of child’s interface

Requires us to explicitly send messages to the class

Restricts operations on child to those that are applicable

Creates an independent type

Makes the use of the parent structure an implementation detail that can easily be changed

Requires us to look at the parent’s as well as child’s protocol

Reuses the parent’s code with no explicit references

Allows all the parent operations to be applied, even those that are meaningless for the child

Allows us to use the child anywhere the parent can be used

Ties the child to choice of the parent structure

Composition versus Inheritance


Bankaccount hierarchy

BankAccount hierarchy

We will write thisclass later

Object

BankAccount

JointBankAccount

Every Java class inherits from the top level Object class.The Object class is the ultimate parent of every Java class


Bankaccount examples

BankAccount Examples

  • Declare two accounts

    BankAccount fred = new

    BankAccount(123, "Fred", 345.50);

    JointBankAccount fredMary = new

    JointBankAccount(345, "Fred", "Mary", 450,65);

  • A joint account is a type of account:

    BankAccount ellenFrank = new

    JointBankAccount(456, "Ellen", "Frank", 3450);

  • The following statement is illegal

    JointBankAccount fred = new

    BankAccount(123, "Fred", 345.50);


Bankaccount examples1

BankAccount Examples

  • Consider the two accounts

    JointBankAccount fredMary = new

    JointBankAccount(345, "Fred", "Mary", 450,65);

    BankAccount ellenFrank = new

    JointBankAccount(456, "Ellen", "Frank", 3450);

  • The following statements are legal

    String owner = fredMary.getOwner();

    String jointOwner = fredMary.getJointOwner();

  • The 2nd statement is illegal

    String owner = fredMary.getOwner();

    String jointOwner = ellenFrank.getJointOwner();


Accountreader example

AccountReader Example

  • Problem: Write an AccountReader class that can read both BankAccount and JointBankAccount objects.

  • Suggests that we need two methods with prototypes

    public BankAccount readBankAccount()

    public JointBankAccount readJointBankAccount()

  • Because of polymorphism only the first version is needed: a joint account "is an" account.


Accountreader example1

AccountReader Example

package booklib;

import booklib.BankAccount;

import booklib.JointBankAccount;

import booklib.KeyboardReader;

public class AccountReader

{

private KeyboardReader input =

new KeyboardReader();

public BankAccount readAccount() {...}

}


Accountreader example2

AccountReader Example

public BankAccount readAccount()

{

// declare local vars

// read account type

// read number, balance, owner

if (type == 2)

{

// read joint owner name

return new JointBankAccount(...);

}

else

return new BankAccount(...);

}

it's also aBankAccount


Accountreadertester

AccountReaderTester

import booklib.*;

public class AccountReaderTester

{

public AccountReaderTester()

{

AccountReader accountInput = new

AccountReader();

BankAccount a = accountInput.readAccount();

System.out.println(a);

}

public static void main(String[] args)

{new AccountReaderTester();

}

}


Tostring is polymorphic

toString is polymorphic

  • The print statementSystem.out.println(a);is shorthand forSystem.out.println(a.toString());

  • the Java run-time system knows whether a refers to a BankAccount object or to a JointBankAccount object so it calls the correct version of the two toString methods


Bank account processing

Bank Account Processing

  • Problem: Read an array of BankAccount objects and process them in several ways.

  • Reading the array is common to all processors

  • Therefore we start with an abstract account processor class that has a non-abstract method to do the account reading and provides an abstract method for account processing

  • Each subclass will provide its own implementation of the processor method.


Accountprocessor

AccountProcessor

abstract public class AccountProcessor

{ private AccountReader inputAccount =

new AccountReader();

protected KeyboardReader console =

new KeyboardReader();

protected BankAccount[] account;

public void readAccounts(){...}

abstract public void processAccounts();

}

subclasses willneed to accessthem

semi-colonis necessary

keyword to indicate abstract classes and methods


Readaccounts method

readAccounts Method

public void readAccounts()

{

System.out.println("How many accounts?");

int size = input.readInt();

account = new BankAccount[size];

for (int k = 0; k < account.length; k++)

{

account[k] = inputAccount.readAccount();

}

}


Maxbalanceprocessor

MaxBalanceProcessor

public class MaxBalanceProcessor

extends AccountProcessor

{

public void processAccounts()

{

double max = account[0].getBalance();

for (int k = 1; k < account.length; k++)

{

double b = account[k].getBalance();

if (b > max) max = b;

}

System.out.println{

"The maximum balance is " + max);

}

}

implement theprocessAccountsmethod


Maxbalanceprocessorrunner

MaxBalanceProcessorRunner

public class MaxBalanceProcessorRunner

{

public static void main(String[] args)

{

MaxBalanceProcessor program =

new MaxBalanceProcessor();

program.readAccounts();

program.processAccounts();

}

}

calls method inAccountProcessor


A fund transfer method

A Fund Transfer Method

  • Problem: Write a method that can be used to transfer a given amount from one bank account to another that works with both BankAccount and JointBankAccount objects:

  • Without polymorphic types we would need four different methods to cover the four possible types of transfer (bank to bank, joint to joint, bank to joint and joint to bank)

  • With polymorphism only one method is needed


A fund transfer method1

A Fund Transfer Method

public void transfer(BankAccount from,

BankAccount to, double amount;

{

boolean ok = from.withdraw(amount);

if (ok)

{

to.deposit(amount);

}

}

  • This works because a JointBankAccount "is a" BankAccount


Using the method

Using the Method

BankAccount fred = new BankAccount(...);

BankAccount joan = new BankAccount(...);

JointBankAccount fredMary =

new JointBankAccount(...);

JointBankAccount joanBob =

new JointBankAccount(...);

transfer(fred, joan, 89.55);

transfer(fred, fredMary, 49.35);

transfer(joanBob, fredMary, 100.00);

transfer(joanBob, joan, 50.00);


Employee hierarchy

Employee Hierarchy

Everything commonto all employees

Employee

Manager

HourlyWorker

PartTimeWorker

These differ onlyin how the salaryis calculated

CommissionWorker


Abstract employee class

Abstract Employee Class

abstract public class Employee

{

private String name;

public Employee(String name)

{this.name = name;

}

public String getName()

{return name;

}

abstract public double grossSalary();

abstract public double netSalary();

}

Constructor forthe name part

polymorphicmethods


Subclasses

Subclasses

  • Manager

    • gross monthly salary,10% deductions.

  • HourlyWorker

    • gross monthly salary from hours worked and hourly wage, 5% ideductions.

  • PartTimeWorker

    • as above with not deductions

  • CommissionWorker

    • like manager with a commission as a percentage of monthly sales


The manager class

The Manager Class

public class Manager extends Employee

{

protected double gross;

protected double net;

public Manager(String name, double salary)

{

super(name);

gross = salary;

net = 0.9 * gross;

}

public double grossSalary() { return gross; }

public double netSalary() { return net; }

public String toString() {...}

}

call superclassconstructor todo its part


Processemployees

ProcessEmployees

public Employee[] staff;

...

public void doCalculations()

{ totalGrossSalary = totalNetSalary = 0.0;

for (int k = 0; k < staff.length; k++)

{

totalGrossSalry += staff[k].grossSalary();

totalNetSalary += staff[k].netSalary();

System.out.println(staff[k]);

}

totalBenefits =

totalGrossSalary - totalNetSalary

}

a polymorphic loop


What is an adapter class

What is an Adapter Class?

  • Inheritance always adds functionality.

  • Sometimes we need to subtract functionality.

  • For example we may want to make a class serve a more specific or simpler purpose by hiding some of its methods.

  • Adapter classes use composition to do this.

  • Our custom format class is an example: hiding the complexity of the DecimalFormat class.


The java util vector class

The java.util.Vector class

  • This is a generic dynamic container class. Some of its constructors and methods are

    public Vector()

    public Vector(int initialCapacity)

    public void addElement(Object obj)

    publicObject elementAt(int k)

    public void setElementAt(int k)

    public int size()

    // convert vector to an Object array

    public Object[] toArray()

    // convert to array of specified type

    public Object[] toArray(Object[] obj)


Vector with bankaccount

Vector with BankAccount

  • Storing BankAccount objects in a Vector container

    Vector v = new Vector();

    v.addElement(new BankAccount(123,"Fred",345.50);

    v.addElement(new BankAccount(345,"Mary",435.43);

    System.out.println(v.elementAt(0));

    System.out.println(v.elementAt(1));

    BankAccount b = (BankAccount) v.elementAt(0);

Object amnesiaagain


Vector with bankaccount1

Vector with BankAccount

  • Converting a Vector to an array

    Vector v = new Vector(1000);

    ...

    BankAccount[] a = new BankAccount[v.size()];

    a = (BankAccount[]) v.toArray(a);

Object amnesiaagain


Bankaccountvector class

BankAccountVector Class

package booklib;

import java.util.Vector;

public class BankAccountVector

{

private Vector v; // composition (hide it)

public BankAccountVector() {...}

public BankAccountVector(int initialCap){...}

public void addAccount(BankAccount b) {...}

public BankAccount getAccount(int k) {...}

public void replaceAccount(BankAccount b,

int k) {...}

public int size() {...}

public BankAccount[] toArray() {...}

}


Bankaccountvector class1

BankAccountVector Class

Constructors

public BankAccountVector()

{

v = new Vector();

}

public BankAccountVector(int initialCap)

{

v = new Vector(initialCapacity);

}


Bankaccountvector class2

BankAccountVector Class

Methods

public void addAccount(BankAccount b)

{

v.addElement(b);

}

public BankAccount getAccount(int k)

{

return (BankAccount) v.elementAt(k);

}


Bankaccountvector class3

BankAccountVector Class

Methods

public void replaceAccount(BankAccount b, int k)

{ v.setElementAt(b,k);

}

publicint size()

{return v.size();

}

public BankAccount[] toArray()

{ BankAccount[] b = new BankAccount[v.size()];

return (BankAccount[]) v.toArray(b);

}


Applying inheritance to solve problems

A Harder Example

  • A Stack Machine is a device that lets you write simple programs that use a Stack

    • Items (in our example numbers) are placed on and removed from the stack using two commands “push” to place on, and “pop” to take off

    • Items are always placed on top of the stack and taken off the top of the stack

  • A stack is a last-in-first-out structure

  • Arithmetic operations can be performed by assuming that the two operands needed for the operation will be the top two items on the stack and the answer will be placed back on the stack


A harder example

A Harder Example

push 5

add

push 10

10

15

5

5

Stack

Stack

Stack

Any mathematical expression can be converted into a series of machine instructions

push 5

push 4

subtract

push 6

multiply

push 5

add

print

5 + (6 * (5 - 4))


Applying inheritance to solve problems

A Harder Example

public static void main(String[] args){

StackMachine sm = new StackMachine();

sm.load(“programFileName”);

sm.run();

}

Clients view:

What are the classes?

StackMachine

Coordinate

all operations

void load(String fileName)

void run()

ProgramLoader

Its purpose is to read the

program in

void load(String filename)

void String getInstruction(int i)

int numInstructions()

Stack

Its purpose is to model

the Stack idea

void push(double value)

double pop()


Applying inheritance to solve problems

Example… gaining an understanding

example.stk

push 5

push 4

subtract

push 6

multiply

push 5

add

print

public class StackMachine{

ProgramLoader pl;

Stack stack;

public StackMachine(){

pl = new ProgramLoader();

stack = new Stack();

}

public void load(String fileName){

pl.load(fileName);

}

public void run(){

String instruction;

for(int i=0; i<pl.

numInstructions(); i++){

instruction = pl.get(i);

System.out.println(instruction);

}

}

Client code

public static void main(String[] args){

StackMachine sm = new StackMachine();

sm.load(“example.stk”);

sm.run();

}

What happens here?


Applying inheritance to solve problems

Implementing the instructions: First Solution

public class StackMachine{

...

public void run(){

String instruction;

for(int i=0; i<pl.numInstructions(); i++){

instruction = pl.get(i);

StringTokenizer st = new StringTokenizer(instruction);

String command = st.nextToken();

if (command.toUpperCase(“PUSH”){

String parameter = st.nextToken();

stack.push(Double.parseDouble(parameter));

}

else if (command.toUpperCase(“PRINT”){

double d = stack.pop();

System.out.println(d);

}

...

}

}

Messy,

long,

yuck, …


Applying inheritance to solve problems

Implementing the instructions: Better Solution

Think of instruction as “classes” and group them

instructions

Organized by

number of parameters

pop

divide

add

push

subtract

print

multiply

one parameter

instruction

no parameter

instruction

Organized by function

arithmetic instructions

instructions

multiply

stack

instructions

divide

add

push

subtract

pop

utility

instructions

print


Applying inheritance to solve problems

Implementing the instructions: Better Solution

Instruction

OneParameterInstruction

NoParameterInstruction

push

print

pop

add

multiply

divide

subtract

Instruction

ArithmeticInstruction

UtilityInstruction

StackInstruction

push

pop

add subtract divide multiply

print

Each instruction will know how to “execute” itself

Each instruction will know how to initialize itself


Applying inheritance to solve problems

Implementing the instructions: Better Solution

public class StackMachine{

...

public void run(){

String instruction;

for(int i=0; i<pl.numInstructions(); i++){

instruction = pl.get(i);

StringTokenizer st = new StringTokenizer(instruction);

String command = st.nextToken();

try{ Instruction instRef =

(Instruction) Class.forName(command)).newInstance();

instRef.load(st);

instRef.execute(stack); } catch(Exception e)

System.out.println(“Syntax error – bad instruction”);

System.exit(0);

}

}

}

}

Client code

public static void main(String[] args){

StackMachine sm = new StackMachine();

sm.load(“example.stk”);

sm.run();}


Applying inheritance to solve problems

Implementing the instructions: Better Solution

public interface Instruction{

public void load(StringTokenizer);

public void execute(Stack);

}

public abstract class ArithmeticInstruction implements Instruction{

public void load(StringTokenizer st){} }

public class Add extends ArithmeticInstruction{

public void execute(Stack stack){

double operand1 = stack.pop();

double operand2 = stack.pop();

stack.push(operand1+operand2);

}

}


Applying inheritance to solve problems

Implementing the instructions: Better Solution

public interface Instruction{

public void load(StringTokenizer);

public void execute(Stack);

}

public abstract class StackInstruction implements Instruction{

// only here for design completeness }

public class PopInstruction extends StackInstruction{

public void load(StringTokenizer st){}

public void execute(Stack stack){

stack.pop();

}

}

public class PushInstruction extends StackInstruction{

double value;

public void load(StringTokenizer st){

String parameter = st.nextToken();

value = Double.parseDouble(parameter); }

public void execute(Stack stack){

stack.push(value); } }


  • Login