0% found this document useful (0 votes)
15 views

Lec07 Inheritance

advanced programming lecture slides

Uploaded by

kushagra22263
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views

Lec07 Inheritance

advanced programming lecture slides

Uploaded by

kushagra22263
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 28

CSE201: Monsoon 2023

Advanced Programming

Lecture 07: Abstract Class and


Immutable Class
Raghava Mutharaju (Section-A)
CSE, IIIT-Delhi
[email protected]
Last Lecture: Inheritance & Polymorphism

Method resolution

● Adding new methods


● Accessing superclass fields/methods
● Overriding superclass methods
● Polymorphism
● Method resolution
This Lecture

● Inheritance and Polymorphism (continued from last


lecture)
● Abstract class and abstract methods
● Immutable classes

Slide acknowledgements: CS15, Brown University

3
Indirectly Accessing private Instance Variables in Superclass by
defining Accessors and Mutators
●Remember from earlier that private
public class Car { variables are not directly inherited by
subclasses
private Radio _myRadio;
●If Car does want its subclasses to be
public Car() {
_myRadio = new Radio(); able to access and change the value
} of _myRadio, it can define protected
protected Radio getRadio(){
accessor and mutator methods
return _myRadio; o Will non-subclasses be able to access
} getRadio() and setRadio() ?
protected void setRadio(Radio
radio){ ●Very carefully consider these design
_myRadio = radio;
}
decisions in your own programs –
which properties will need to be
} accessible to other classes? 4
Andries van Dam © 2016 9/22/16
Calling Accessors/Mutators From Subclass
●Convertible can get a reference
to _radio by calling
this.getRadio() public class Convertible extends Car {
public Convertible() {
o Subclasses automatically inherit }
these public accessor and mutator
public void setRadioPresets(){
methods this.getRadio().setFavorite(1,
●Note that using “double dot” we’ve 95.5);
this.getRadio().setFavorite(2,
chained two methods together 92.3);
o First, getRadio is called, and }
}
returns the radio
o Next, setFavorite is called on
that radio
5
Andries van Dam © 2016 9/22/16
Let’s step through some code
●Somewhere in our code, a Convertible is instantiated

//somewhere in the program


Convertible convertible = new
Convertible();
convertible.setRadioPresets();

●The next line of code calls setRadioPresets()


●Let’s step into setRadioPresets()

6
Andries van Dam © 2016 9/22/16
Let’s step through some code
public class Convertible extends Car {
●When someone calls public Convertible() { //code elided
}
setRadioPresets(); first line
is this.getRadio() public void setRadioPresets() {
this.getRadio().setFavorite(1, 95.5);
●getRadio() returns _myRadio this.getRadio().setFavorite(2, 92.3);
}
●What is the value of _myRadio }
at this point in the code?
o Has it been initialized? public class Car {
o Nope, assuming that the private Radio _myRadio;
structure of class Car is exactly
as shown on right side (i.e. public Radio getRadio() {
without any constructor), we’ll run return _myRadio;
into a NullPointerException }
}
here :( 7
Andries van Dam © 2016 9/22/16
Making Sure Superclass’s Instance Variables are Initialized

●Convertible may declare its own instance variables,


which it initializes in its constructor
●Car’s instance variables are initialized in the Car
constructor
●When we instantiate Convertible, how can we make sure
Car’s instance variables are initialized too?
o Case-1: Car has a default constructor that instantiate all its fields
o Case-2: Car has a parameterized constructor for initializing all its
fields

8
Andries van Dam © 2016 9/22/16
super(): Invoking Superclass’s Default Constructor (Case 1)

● Let’s assume that Car’s instance


variables (like _radio) are initialized public class Convertible extends Car {
in Car’s default constructor
private ConvertibleTop _top;
● Whenever we instantiate
Convertible, default constructor of public Convertible() {
Car is called automatically super();
_top = new ConvertibleTop();
● To explicitly invoke Car’s default this.setRadioPresets();
}
constructor, we can call super()
inside the constructor of public void setRadioPresets(){
Convertible this.getRadio().setFavorite(1,
o Can only make this call once, and it 95.5);
this.getRadio().setFavorite(2,
must be the very first line in the subclass’s
92.3);
constructor
}
}
9
Andries van Dam © 2016 9/22/16
super(): Invoking Superclass’s Parameterized Constructor (Case 2)
public class Car {
●What if the superclass’s constructor
private Racer _driver; takes in a parameter?
public Car(Racer driver) {
_driver = driver;
o We’ve modified Car’s constructor to take
} in a Racer as a parameter
...... o How do we invoke this constructor
}
correctly from the subclass?
●In this case, need the
public class Convertible extends
Car {
Convertible’s constructor to also
take in a Racer
private ConvertibleTop _top;
●The Racer is then passed as an
public Convertible(Racer
driver) { argument to super() – now Racer’s
super(driver); constructor will initialize _driver to
_top = new
ConvertibleTop(); the instance of Racer that was
} passed to the Convertible
10
...... Andries van Dam © 2016 9/22/16
What if we don’t call super()?
●What if we forget to call super()?
●If you don’t explicitly call super() first public class Convertible extends Car {

thing in your constructor, Java private ConvertibleTop _top;


automatically calls it for you, passing in
public Convertible(Racer driver) {
no arguments //oops forgot to call super()
_top = new ConvertibleTop();
●But if superclass’s constructor requires }
a parameter, you’ll get an error!
......
●In this case, we get a compiler error }

saying that there is no constructor


“public Car()”, since it was
declared with a parameter
11
Andries van Dam © 2016 9/22/16
How to Load Passengers?
●What if we wanted to seat all of
the passengers in the car?
●Sedan, Convertible, and Van all
have different numbers of seats
o They will all have different
implementations of the same
method

12
Andries van Dam © 2016 9/22/16
Solution-1: Using Constructor Parameters
public class Convertible extends Car {
private Passenger _p1;
public Convertible(Racer driver, Passenger
p1) {
super(driver); • Notice how we only
_p1 = p1;
} need to pass driver
//code with passengers elided to super()
}
• We can add additional
public class Sedan extends Car {
private Passenger _p1, _p2, _p3, _p4; parameters in the
public Sedan(Racer driver, Passenger p1, constructor that only
Passenger p2, Passenger p3, Passenger p4) {
super(driver); the subclasses will use
_p1 = p1; • Note that super() has
_p2 = p2;
_p3 = p4; to be the first
} statement inside the
//code with passengers elided
} constructor. 13
Andries van Dam © 2016 9/22/16
Any drawbacks in Previous Approach?
● How about creating an interface Passengers with a
method loadPassenger?
o Which class should implement that?
 Superclass (Car) or Subclasses (Convertible, Sedan, and Van) ?
o Issues
 Creating an extra interface (possibly a new file)
 Each subclass should have the declaration in the following form:
• public class Sedan extends Car implements Passengers { …. }

14
© Vivek Kumar
abstract Methods and Classes
●We declare a method abstract in a superclass when the
subclasses can’t really re-use any implementation the
superclass might provide
●In this case, we know that all Cars should
loadPassengers, but each subclass will
loadPassengers very differently
●abstract method is declared in superclass, but not
defined – up to subclasses farther down hierarchy to provide
their own implementations

15
Andries van Dam © 2016 9/22/16
Solution-2: Using abstract Methods and Classes
●Here, we’ve modified Car to make it
an abstract class: a class with
preferably an abstract method public abstract class Car {
o You can avoid abstract method and just private Racer _driver;
mark class as abstract if you don’t wish to
allow object creation of this class public Car(Racer driver) {
●We declare both Car and its _driver = driver;
}
loadPassengers method
abstract: if one of a class’s public abstract void
methods is abstract, the class itself loadPassengers();
must also be declared abstract
}
●An abstract method is only
declared by the superclass, not
implemented – use semicolon after
declaration instead of curly braces
16
Andries van Dam © 2016 9/22/16
Solution-2: Using abstract Methods and Classes
public class Sedan extends Car{
public class Convertible extends Car{ @Override
@Override public void loadPassengers(){
public void loadPassengers(){ Passenger p1 = new Passenger();
Passenger p1 = new Passenger(); p1.sit();
p1.sit(); ......
} Passenger p3 = new Passenger();
} p3.sit();
}
}

public class Van extends Car{


@Override ● All concrete subclasses of Car
public void loadPassengers(){
Passenger p1 = new Passenger(); override by providing a concrete
p1.sit(); implementation for Car’s abstract
..... loadPassengers() method
.....
Passenger p6 = new Passenger(); ● As usual, method signature must
p6.sit(); match the one that Car declared
}
} 17
Andries van Dam © 2016 9/22/16
abstract Methods and Classes
● abstract classes cannot be instantiated!
o This makes sense – shouldn’t be able to just instantiate a generic Car, since it has no
code to loadPassengers()
o Instead, provide implementation of loadPassengers() in concrete subclass, and
instantiate subclass
● Subclass at any level in inheritance hierarchy can make abstract method
concrete by providing implementation
● Even though an abstract class can’t be instantiated, its constructor must still be
invoked via super() by a subclass
o because only the superclass knows about (and therefore only it can initialize) its own
instance variables

18
Andries van Dam © 2016 9/22/16
So.. What’s the difference?
●You might be wondering: what’s the difference between abstract
classes and interfaces?
●abstract Classes:
o Can define instance variables
o Can define a mix of concrete and abstract methods
o You can only inherit from one class
●Interfaces:
o Cannot define only instance variables/concrete methods
o You can implement multiple interfaces

Note: Java, like most programming languages, is evolving. In Java 8, interfaces and abstract classes are
even closer in that you can have concrete methods in interfaces. We will not make use of this in CSE201.
19
Andries van Dam © 2016 9/22/16
What if the Cars are Getting Modified?
No modifications
should ever be
allowed !!

20
© Vivek Kumar
Immutable Classes (1/5) 1. Don't provide any methods
that modify the object's
state.
2. Make all fields private.
(ensure encapsulation)
3. Make all fields final.

public class Mechanics {


private final String oilType;
private final int numCylinders;
public Mechanics(String oil, int cylinders)
public String getOilType();
public int getNumCylinders();
21
} © Vivek Kumar
Question
● Immutable classes have their fields marked as final. Then,
why can’t we make those fields as public and let clients
access them without any getter methods ?

© Vivek Kumar 22
Immutable Classes (2/5) 1. Don't provide any methods
that modify the object's
state.
2. Make all fields private.
(ensure encapsulation)
3. Make all fields final.

public class Mechanics {


public final Tire tire;
.......
public Tire getTire(){return tire;} public class Tire {
private int size;
} public int getSize();
public void setSize(int);
// The user can easily do this: }
23
mechanics.tire.setSize(20); © Vivek Kumar
Immutable Classes (3/5) 1. Don't provide any methods
that modify the object's
state.
2. Make all fields private.
(ensure encapsulation)
3. Make all fields final.

public class Mechanics {


private final Tire tire;
.......
public Tire getTire(){return tire;} public class Tire {
private int size;
} public int getSize();
public void setSize(int);
// The user can easily do this: }
24
mechanics.getTire().setSize(20); © Vivek Kumar
Immutable Classes (4/5)
public class Mechanics {
private final String oilType;
private final int numCylinders;

public Mechanics(String oil, int cylinders)


public String getOilType();
public int getNumCylinders();
}

public class ModifiedMechanics extends Mechanics {

...... How to fix


@Override How to fix this?
public String getOilType(){ these?
return “Rocket Fuel”;
}
@Override
public int getNumCylinders(){return 18;}//Bugatti
}
© Vivek Kumar 25
Immutable Classes (5/5)
public final class Mechanics {
private final String oilType;
private final int numCylinders;

public Mechanics(String oil, int cylinders)


public String getOilType();
public int getNumCylinders();
}

public class ModifiedMechanics extends Mechanics {

......
Mechanics cannot be @Override
extended as it is declared public String getOilType(){
return “Rocket Fuel”;
as final }
@Override
public int getNumCylinders(){return 18;}//Bugatti
}
© Vivek Kumar 26
Summary: Making a Class Immutable
1. Don't provide any methods that modify the object's state.
2. Make all fields private. (ensure encapsulation)
3. Make all fields final.
4. Ensure exclusive access to any mutable object fields.
o Don't let a client get a reference to a field that is a mutable object (don't
allow any mutable representation exposure.)
5. Ensure that the class cannot be extended.

© Vivek Kumar 27
Next Lecture
● Class Object

28

You might also like