You are on page 1of 88

Unit #2 – Object

Oriented
Programming in Java
Introduction …
• The Java language is (mostly) object-oriented. What exactly does that mean? We will see
shortly. Let’s discuss first how you wrote code last year first.
• Last year, you used Python to write code that embraced what is called a structured-
programming paradigm. Python is capable of OOP, but your learning did not focus on that
aspect of Python. Trying to learn a first programming language and OOP simultaneously
can be overwhelming, and structured programming is where we all begin our journey.
• In structured programming, one uses data structures and program instructions that act on
data.
• Object-oriented languages combine data and program instructions into what are called
objects.
• Instead of having a data structure with fields (attributes) and passing that structure around
to all of the program logic that acts on it (behavior), in an object-oriented language, data
and program logic are combined.
What is it?
Object oriented programming is a model of programing that focuses on objects and the data
associated with the object.

Objects are structures that contain both state and behaviour.


An object’s state is the data about the object.
An object’s behaviour are the actions that the object performs.

Classes are templates for creating objects.


Principles of Object
Oriented
Programming
• There are four defining principles
of OOP:
• Abstraction
• Encapsulation
• Inheritance
• Polymorphism.
Abstraction
• Abstraction aims to hide complexity and show only relevant information. For example, if you’re
driving a car, you don’t need to know about its internal workings.
• You can hide internal implementation details using abstract classes or interfaces. On the abstract
level, you only need to define the method signatures (name and parameter list) and let each class
implement them in their own way.
• Abstraction in Java:
• Hides the underlying complexity of data
• Helps avoid repetitive code
• Presents only the signature of internal functionality
• Gives flexibility to programmers to change the implementation of abstract behavior
• Either Partial abstraction (abstract classes) or total abstraction (using interfaces) can be
achieved.
Encapsulation
• Encapsulation helps with data security, allowing you to protect the data stored in a class
from system-wide access. As the name suggests, it safeguards the internal contents of a
class like a capsule.
• You can implement encapsulation in Java by making the fields (class variables) private and
accessing them via their public accessor and mutator methods often referred to as
getters and setters.
• The internal workings of the class as to how things work should not be visible or
accessible to the ”rest of the world”
• Encapsulation in Java:
• Restricts direct access to data members (fields) of a class
• Fields are set to private
• Each field has a getter and setter method
• Accessor/Getter methods return the field
• Mutator/Setter methods let us change the value of the field
Inheritance
• Inheritance makes it possible to create a child class that inherits the fields and methods of the parent
class.
• The child class can override the values and methods of the parent class, but it’s not necessary. It can
also add new data and functionality to its parent.
• Parent classes are also called superclasses or base classes, while child classes are known as subclasses
or derived classes as well. Java uses the extends keyword to implement the principle of inheritance in
code.
• Inheritance in Java:
• A class (child class) can extend another class (parent class) by inheriting its features
• Implements the DRY (Don’t Repeat Yourself) programming principle
• Improves code reusability
• Multi-level inheritance is allowed in Java (a child class can have its own child class as well)
• Multiple inheritances are not allowed in Java (a class can’t extend more than one class)
Polymorphism
• Polymorphism refers to the ability to perform a certain action in different ways. In Java,
polymorphism can take two forms: method overloading and method overriding.
• Method overloading happens when various methods with the same name are present
in a class. When they are called, they are differentiated by the number, order, or types
of their parameters. An example of static polymorphism..
• Method overriding occurs when a child class overrides a method of its parent. An
example of dynamitic polymorphism.
• The same method name is used several times
• Different methods of the same name can be called from an object.
Parent and child objects …
• A parent object is one that serves as the structural basis for deriving more-complex child
objects. A child object looks like its parent but is more specialized. With the object-oriented
paradigm, you can reuse the common attributes and behavior of the parent object, adding
to its child objects attributes and behavior that differ.
• Objects “talk” to other objects by sending messages – i.e. method calls. In an object-
oriented application, program code coordinates activates among objects to perform the
required tasks of the software that solves a given problem.
• A well-written object:
• Has well-defined boundaries
• Performs a finite set of activities
• Knows only about its data and any other objects that it needs to accomplish its
activities
What We Don’t Know That We Know
• You are already using classes and objects in your programs.
• Consider when we create a string variable. Up until now we would
simply write: String myString = "word"; This creates a variable, or
reference variable, called myString and hold the value of “word”.
• We saw in the previous unit that a more formal way of creating a String
variable existed. The creation of the instance, or object, called str is
called instantiation, and we did so using the following code:
What We Don’t Know That We Know
• You may recall typing the following code when prompting the user for input:

• But what exactly is going on? What does this really do?

• The left side of that equation declares a reference variable named objectVariable of
type ClassName. This is the declaration part of the statement. We are telling the
compiler that we want to create a variable named objectVariable of the Class
ClassName type.
• The right side of the equation is responsible for instantiating an object of type
ClassName. The keyword “new” is used to create a new instance of the class named
ClassName. The Constructor creates an instance of that object.
• Constructors may also be overloaded!
• In some cases, we will declare the object but not instantiate it until “later”. This
approach is like declaring a primitive data type and later assigning a value to it, but NOT
exactly. I did say ”like” didn’t I?
More on Objects
Consider:
• A rectangle is an object and it has a certain state (its dimensions):
Length = 4
Width = 2

• And perhaps that object has a behaviour (the calculation of its area,
or its perimeter):
Area = 8 Perimeter=12

• So, it could be said that all rectangles have a length and a width, and
from that information a rectangles area can be determined.
Classes Are Not Just For School
• Based on that we can create a blueprint of what a rectangle is. You
could say that a rectangle is an individual class of geometric shapes.
• And from that template we can create many different types of
rectangles. 2h=
Lengt = 1
Width
Length =
Rectangle 4
Width = 2
Length
Width
Length = 2
th =2 Width = 4
g 6
Len dth =
Wi
Rectangle Class Creation
• To be able to create this blueprint, or class, that will allow us to create
multiple object we will need some code as follows:
• Pay careful attention to my explanation of the this portion of the
code!!!!
Rectangle
Length
Width
Class Anatomy
If the public or private access modifier is not
• Name the class and open the specified, a field is assumed to be public.
Making fields of a class public as done here
code block. goes against the OOP principle of
• Attributes are variables of the encapsulation. We will fix this shortly.
object when its created.
• A constructor provides
instructions on how an object
is to be created.
Note: Although not seen in this
slide, classes may also contain
methods and more than one
constructor.
Class Instantiation
Now that there is a class for rectangles, we can easily call our class with some
code and create more than one rectangle object with different states:

Obvious, but important to state. Both classes are within the same project, and
only the class TestShape has the main() method. Again, the Rectangle class
does NOT have a main() method!
What now?
• At this point, this is what our project looks like. It doesn’t actually
show any output … yet. Take a moment create these classes and type
the necessary code.
Important Note:
I have fixed the fields length
and width to be deliberately
public. This is not ideal, as
one can access an instance’s
length or width field by using
.length or .width after the
name of the object.
These sort of implementation
details should not be visible to
other methods as it goes
against the OOP principle of
encapsulation!
Lettuce Let us Lettuce J Review
We have learned how to:
• Create a class called Rectangle
• Create instance variables that
serve as the attributes for the
class. For now they are public …
• Create a constructor for the
class, providing instructions on
how an instance of the class
should be instantiated.
• Create an instance of our class.
Running your program at this
point does not produce any
output.
Wait just a second …
• Let’s go back and revisit the signature of methods we wrote when we were
younger back in unit #1. Our methods had the following signature:

• Private means that the method is only available to the class its created in.
• Static means that it can be accessed without creating a separate instance of the
class. Methods that are created within the same class as the main method
MUST be static if they are to be called from the main or other method within
the class containing the main() method.
• Void means that this method does not return a value. If we have a return
value, we must specify its type here instead of void.
A Little More On The Code
So far, our code looks like this:
And if you look at lines 3 and 4
of the Rectangle class, we have
our instance variables length
and width. The variables
belong to the objects we create
and are recreated each time a
new object is instantiated. This
is why they are called INSTANCE
VARIABLES.
rectangleA rectangleB
length=2 length=5
width=4 width=6
A Little More On The Code
Heap
In memory it looks something
like this: Rectangle
length=5
Stack
main() width=6
rectangleB
Rectangle
rectangleA
length=2
width=4
Classes with Methods
Let’s Override the toString() Method
• Every object inherits a toString() method. It provides you with a string
representation of the object as an object name and its hexadecimal
hashcode.
• Usage:
• Using a toString method is automatic behind the scenes so to speak when
applied in a println statement. Assigning an objects String representation to a
string variable requires a toString() method call.
Well that was … useless 🤪
• Don’t fret … we will be overriding the method toString() to make it more
useful.

• Here we have replaced the default toString() that is inherited from the
Object class. This is called overriding. All objects we create will inherit from
the Object class. In fact, we can still call the code from the parent class along
with our new code using the super keyword. This is handy should we also
want the hashcode as well J Usually not.:
Wouldn’t it be fun if we …
• What if we override the default toString() method with the following code:

• This is the beauty of OOP.


• My main method has had zero changes to its code.
• By modifying the toString() method of the Rectangle class this implementation detail
and upgrade has been completely hidden from the classes that would use the
Rectangle class! They access the toString() method as usual, but now have a new
different output!
Bad OOP programming vs. Good OOP Programming …

• Accessing another classes’ instance variables (often referred to as fields)


in this method is considered bad OOP programming:

• This is permitted because the instance variables are currently set to


public in the Rectangle class. We should tighten this up and force any
class that uses the rectangle class to access the fields a different way
should their implementation ever be changed.
Privacy is a GOOD thing!
• It is better, and for reasons that we will thank ourselves for later in our
programming experience, to make our instance variables private.

• Once that happens, they are only accessible from within the object’s
instance.

• How do we permit access to the fields then? Simple. On our own terms!
Quick tangent … but an important one!
• For this demo here, I will go back and set the instance variables to public. Let’s
examine the following code and it’s output.

• Why did this happen?


• Simple. The secondRectangle is pointing to the location in memory of the first object.
• As such, we can modify the first’s length by simply changing its field being referenced from the
secondRectangle object! This is of course by design.
• There is technically only ONE instance of the rectangle object, the two variables are sharing …
awwe isn’t that cute. They’re sharing like in kindergarten … NO, no it is not. Changes to one
variable’s field’s affect the other! This may or may not be what one is expecting so be careful!
• Forcing one to use a mutator or accessor makes the programmer think when using another’s
Class. The class designer would encapsulate their code providing access to only things that will
not put their Class in an unstable state. But more on that in a bit J.
Tangent Continued …
• If instead our code was as such:

• Our length field of the first rectangle did not change. Why? Again the
firstRectangle and secondRectangle are reference variables referring to
different locations in memory where their respective field variables are
stored.
• There are after all two different instances of the rectangle object.
Creating Getters (Accessors) and
Setters (Mutators)
• Getters are methods that are written in the class to provide the “outside” world
controlled viewing of private instance variables we wish to expose. Or provide access to
class level variables (more on these in a bit).
• Getters have a return type.
• Setters do not have a return type but must have parameters which are used to set the
values of the private instance variables to.
• This is the OOP principle of encapsulation in action!
What is a setter?
• Setters are methods that are written in the class to provide the
“outside” world access to change private instance or class variables we
choose to expose.
• Keep in mind that the author of the Class may not end up being the
only one that uses the class. Another programmer may use its
functionality.
• This is where the problems begin. What if they inadvertently modify an object’s
fields directly and place it in a bad state.
• They after all may not understand the inner workings of the class (nor do they
need to). It is the job of the original class author to properly encapsulate their
method and protect it from bad data that would put it in an unstable state.
• Here I will place the secondRectangle object which is an instance of the
Rectangle class in a bad state. Any computations performed on the
instance will be invalid, except of course the area.
Setters Continued …
• We can even create more than one setter should we choose.
• The following are the simplest setters for the length and width fields.

• Usage would be within our main method (or other method accessing
the Rectangle class from outside the class):
More Complicated Setters …
• We can also check that the required change to the private variable does not put our
object in an unstable state.
• I will use the throw command which will instantly crash the program.
• One can catch a thrown exception and handle it with other code, but that is another
story which will be told later.
• Not graceful, but it is better that whoever is using your class know immediately that
they have placed an object in an unstable state than to permit program execution to
continue and provide unreliable results.
• This way THEIR code can be fixed to use your class correctly! The code that uses the
class should then be modified so as to not call a setter if it puts the object in an
unstable state.
Thowing things around …
• Main code:
• One implementation:

• Another possible implementation: (preferred)


Important Distinction …
• Now that you have learned in a few places how to throw an exception, you should be taught WHEN to throw
an exception!
• For example, if you are prompting the user of your program for the length and width of a rectangle, or the
hourly rate of an employee you should NOT throw an exception if they enter a negative value. You simply re-
prompt the user to enter the correct data. This is where your Utils.inputInteger method comes in handy …
• BUT … if you are writing the a class called Employee with a private double variable hourlySalary, you should
not allow another PROGRAMMER using your class to possibly store a negative value there. You MUST throw
an exception within your Employee class to protect it from going into an unstable state.
• There is a subtle distinction here. The user of your Class is another programmer. They may or may not know
the inner workings of your Class nor should they have to ... They use getters and setters to access and
modify class variables. That’s it. Nothing more, nothing less. The Class author is responsible for protecting
their code from being put in an invalid state.
• Super important … setters do NOT prompt for input … they simply take what is given as an argument to the
method call and store it in the appropriate variable. I repeat, Your class does NOT prompt the user for any
input! , Your class does NOT prompt the user for any input! I say this not twice but thrice because its
important! See next slide for details …
Getters …
• Getters are much easier to code as they simply
return the value of the private instance field.
• It is good programming practice to keep all the
getters together in one section and setters
together in another section of the class
definition. This makes it easier to find code and
make changes.
• The advantage of using getters is of course one
does not need to worry about about the field
variable names within a class.
• NOTICE THAT THE GETTER DOES NOT OUTPUT
ANY VALUES, IT RETURNS THE APPROPRIATE
FIELD VARIABLE TO THE CALLING METHOD!
S’more getters …
• We can also write code that will return the result of a computation
based on the current state of the object. In this case, we can
determine the area and perimeter by creating getters and calling
them within our main method of our Main class.

• We may even want to incorporate these results in our toString()


method of our Rectangle class as well.

Note that here I specifically called the getters


getArea() and getPerimeter(). Why? Should their
implementation every change, I do not need to
change the toString() method.
WHY OH WHY ….
• Why should getters and setters not display or prompt the user the
variable to the console or obtain input from the user directly?
Because I said so! No seriously, there is a reason for this …
• Remember … the class sets up your data structure that allows
functionality for the rest of your app and MUST be independent of
whether one uses the console for input/output or a GUI !
• As a rule of thumb, moving forward your methods should avoid
outputting results to the console if possible, and simply return a value
(int, double, String ) which will be acted upon from the calling
method. This will make your transition to GUI a smoother one J
• Our main code and output now:
Comparing Rectangles
• What does it mean for two rectangles to be equal? I donno … do you?
• Let’s examine the following code and output:

• Why do they not work? Simple. Remember that the == operator only works
for primitive variable types. Objects are reference types.
• Luckily there is a .equals Method that is inherited from the Object class.
Inherited .equals method
• The inherited .equals method’s usage is shown here:

• Unfortunately, it does not work either as it will compare only the


hashcodes of the two objects. Besides what does it mean for two
rectangles to be equal anyways?
Overriding the .equals method
• We should override the .equals method to make it more useful!
• By adding this code to our Rectangle class, our main method from our
Main class will function correctly!

• That’s ugly … let us recode that … yes ….


But there is still a problem …

• These are technically the same rectangle! Let’s adjust the .equals method a wee
bit more to accommodate for this:

• Yay!!! It works properly!


Now what?
• Having established whether two Rectangle objects are equal, let’s discuss what it means
for one rectangle to be less than the other.
• What will be the metric? Let’s choose the rectangle area and implement the following
using the rectangles’ area as the metric. We want to implement:
• source.compareTo (other):
• Zero if the two rectangles are equal
• If source area < other area, returns a value of -1
• If source area > other area, returns a value of 1

• If our metric changes to perimeter, then we will need to change this code so the
respective perimeters are compared.
• For another object say an Employee object, we may choose the employee’s name to
decide on which Employee object is smaller. More on that later.
So far …
Let’s recap.
A class is essentially a blueprint for creating objects.
A class will have attributes, qualities that make it what it is.
These would be the classes instance variables
A class will also have behaviours. Behaviours are the things that it does
These would be the methods that we create within our class.
When we instantiate a new object we create an instance of that class
with its own attributes and behaviours defined by its class.
Diagramming Classes with UML
• Programmers will often draw class
diagrams to illustrate the relationship
among the classes that make up their
program(s).
• The diagram on the right shows four
classes, and the relationship between
those classes.
Diagramming Classes with UML
• Programmers use a diagramming standard called UML, which stands for Unified Modeling Language.
• A UML diagram helps programmers organize the programming design process in a way that clients,
analysts and other programmers can understand and agree on. The following are a list of just some of he
benefits of using UML:
• Your software system is professionally designed and documented before it is coded. You will know exactly what you
are getting, in advance.
• Since system design comes first, reusable code is easily spotted and coded with the highest efficiency. You will have
lower development costs.
• Logic 'holes' can be spotted in the design drawings. Your software will behave as you expect it to. There are fewer
surprises.
• The overall system design will dictate the way the software is developed. The right decisions are made before you are
married to poorly written code. Again, your overall costs will be less.
• UML lets us see the big picture. We can develop more memory and processor efficient systems.
• When we come back to make modifications to your system, it is much easier to work on a system that has UML
documentation. Much less 'relearning' takes place. Your system maintenance costs will be lower.
• If you should find the need to work with another developer, the UML diagrams will allow them to get up to speed
quickly in your custom system. Think of it as a schematic to a radio. How could a tech fix it without it?
• If we need to communicate with outside contractors or even your own programmers, it is much more efficient.
Drawing Classes
• The basic element in a class diagram is a class. In UML, each class is drawn
as a rectangle.
• At the very least, the rectangle must include the class name. It can also be
subdivided into two or three sections that can contain additional information
about the class (i.e. field variables, constructors, methods, etc.). The following
class diagram includes the class name, variables and methods
Drawing Classes Continued …
• In class diagrams, the fields are denoted as:
variableName: variableType
• The constructors are denoted as:
ClassName(parameterName: parameterType)
• The methods are denoted as:
methodName(parameterName: parameterType): returnType
• The idea here is that these are language independent yet provide just enough information to see the general
structure of the class.
• The name of each variable or method can be preceded by a visibility indicator. The following are a list of the
visibility indicators for class variables and methods

Indicator Visibility Description


+ Public Makes classes, methods and data fields accessible from any class.

- Private Makes methods and data fields accessible only from within its own class.

# Protected Can be accessed by any class in the same package or its subclasses
Practice drawing a UML Class Diagram:
• Draw UML diagrams for the following two classes we have done as a
class:
• Rectangle
• User
Let’s Code it Together

Together we will create a triangle


class and on your own you’ll create
a circle class.
What should we have ??
Could you start building something?

• Given this UML Class Diagram … build a Car … class that is J


Car Class
-ownerName: String
-make: String
-odometerReading:double
Car()
Car(ownerName:String, make: String,odometerReading:double)
+getOwnerName(): String
+setMake(value:String):void
+getMake():String
+getOdometerReading(): double
+setOdometerReading(value:double):void
+setOwnerName(power:String):void
+toString():String
Unstable State ? Tell me more … sure …
Overloading
Constructors
Let’s Revisit our constructors
Why overload Constructors?
• Overloading a constructor has some advantages:
• Overloaded constructors allow you to initialize an object with different values or
configurations. This is useful when you want to create objects with varying initial states.
• You can have one constructor call another constructor within the same class using `this()`.
This is useful for reusing code and ensuring that common initialization logic is centralized.
• Overloaded constructors provide flexibility to users of the class. They can choose the
constructor that best suits their needs by passing the appropriate arguments. This helps in
making the class more user-friendly.
• You can provide default values for certain parameters, so if a user does not specify a value,
the constructor can use the defaults. This simplifies object creation and reduces the need
for numerous constructors.
• Overloaded constructors contribute to method overloading and polymorphism, which is a
fundamental concept in object-oriented programming. This allows you to have different
methods with the same name in a class, differentiating them based on their parameter lists.
• Overloaded constructors can be used to enforce certain validation rules or constraints on
object creation. For example, you can check if the provided arguments are valid and throw
exceptions if not.
Overloading …
• By now you should be thinking in our constructor should we not use
our setters rather than directly access the fields?

• I would say … YES. Why? Remember we wrote code in our setters


that would take care of unstable class level fields? We wouldn’t want
to duplicate that code yet again. Remember the DRY principle!
• Let’s see if we can now overload the constructor class.
So our constructors of the Rectangle class are:
Here is another example of overloading …
Overloading …
• What if one wanted to make a square and only specify one argument in
their call to the constructor for the class Rectangle.

• We have just gone and repeated ourselves! We have just gone and
repeated ourselves! We have just gone and repeated ourselves … Instead
code things like this. Here I have created a
constructor with no
parameters. This could
be handy if you want to
create Rectangle objects
and don’t know the
dimensions just yet. One
can set them later with
appropriate setters.
Things are about
to get …
Compli-mi-kated!
Why oh why?
• Suppose we have a class SomeItem with instance variables:
• username (String), age (int) and accountBalance (double)
• We have implemented a second class called SomeItems which will allow us to store an almost limitless
number of SomeItem instances within an array called itemsArray that resizes as needed.
• Within our Main class with our main method (or other classes for that matter), we cannot and MUST
NOT access the itemsArray directly as this breaks two of the fundamental principles of OOP – abstraction
and encapsulation.
• The internal complexity of that class is not and should not be of concern, nor should we simply allow
another coder to go and monkey around with things. We want controlled access to our Class.
• Put simply, you MUST NOT directly allow for the coding like the following from outside the class
SomeItems as this can cause catastrophic results of epic proportions should those using your class do so
incorrectly. We are talking cosmic level catastrophe here!

• We must instead provide controlled access to our internal data structure that is used.
So how do I do it then? But how ??
• Two solutions that exist. Either we can mirror every getter/setter from our SomeItem class with
an additional parameter as to which target in our SomeItems class like this:

• Then use only using getters and setters like these to control access to the internal workings of
the SomeItems class.
• Easy enough to implement but there are a few drawbacks - first it violate the DRY principle as
you could imagine the mess that would result if the SomeItem class had numerous instance
variables.
• This approach bloats our SomeItems class with repeated logic making code less maintainable.
There is a slicker and more powerful way …
• This method involves the chaining of method calls but we must be
careful here that any link within the chain cannot cause an exception.
• We start by adding a method to our SomeItems class that returns the
instance within the itemsArray we are searching for as shown here:

Don’t forget that the itemsArray is an


array of type SomeItem

https://onlinegdb.com/l_16JiJTA
Now the main part …
• Within our Main class, should we want to access accountBalance instance
variable belonging to our good friend Cookie Monster, we use:

• Changing it? Simple …

• But be careful, you could get into trouble if you chain things that could
cause an exception …

This behaves … as expected!


We need to protect this from
happening …
Let’s protect that call ….
• Did you see the method called exists within our our SomeItems Class
which operated on a String parameter and returned a boolean result?
• Lettuce use it …
I am going to
protect my cookies
while you do that!

https://onlinegdb.com/6p8bXERhv
Lettuce examine …
• Go back to the current Donut project … the following code should
make more sense …
Persons instance (implements an array of type Person)

Person instance

Franchises instance (which implements an array of type Franchise)

The result is launching the vendDonut method with


Franchise instance (which has an array of Donut) the correct number of donuts, on the correct donut
instance, from the correct franchise instance from the
Franchises instance!
Whew … C.M. gimme one of those!
Donut instance What if we had Franchises instances within a country –
that makes me really hungry … better yet gimme two!
Last thoughts …
• Over the past week, we have been using a fixed size array and allowed it to grow
dynamically.
• But we haven’t addressed removing items from the array of items …
• How do we implement the removal of an item from within our fixed size array? We
employ a small trick.
• We find the item we want to delete and rather than shifting all the elements ”up one spot”, we
copy the last item within our fixed size array to the index of the entry we wish to delete.
• We then deduct one from our currentLastSpot instance variable. This makes our used fixed size
array smaller without needed to shift significant number of entries around. The next add will go
exactly where it should – all done J.
• This approach is better than shifting data up one spot as if the array is very large, one would
incur very costly moves.
• You can see it in action here: https://onlinegdb.com/hMgdqQTg5
• Notable things to look for – a modified toString() method, the delete method (of
course) and the algorithm used.
• There is of course another algorithm, but this one is easiest.
Static Fields
Fields that DON’T move? Surely you jest …
Well maybe I am not jesting …
Using a static field within a class
• A static field is a class-level variable that belongs to the class rather than any specific
instance of the class. It is shared among all instances of the class and is initialized
only once when the class is first loaded into memory.
• Static fields are declared using the static keyword.
• Static fields are typically accessed using the class name, rather than going through
an instance of the class, although you can go through any instance of a class and
access the same static variable and contents.
• Static fields are useful for maintaining values that are common to all instances of a
class. They are often used for constants, or variables that need to be shared among
all instances of a class.
• Modifying a static field affects all instances of the class – changes are visible across
the entire class.
• Very important:
• To access a static field within the Class, one uses the ClassName.fieldName you do not use
this.fieldName as that references an instance variable, NOT a Class level variable.
• Any methods within the Class that change or return the static variable need to be declared as
static.
Using a static field within a class
• When working with static fields in a class, there are a few important rules to keep in mind,
especially when designing getter and setter methods for these fields:
• A static field can be accessed within a class through a static method (getter). The method should also
be declared as static. In the same class, a static field can also be accessed directly without using a
getter although best to use a getter to be consistent.
• A static field can be modified within a class through a static method (setter). The method should be
declared as static. A static field can be modified directly within the class without using a setter but
always use the setter to ensure that it does not go in an unstable state.

• Access modifiers (public, private, protected, etc.) still apply to static fields and their
accessor/mutator methods.
• It is a good practice to encapsulate static fields by making them private and
providing public getter and setter methods if needed.
• Using static methods for static fields makes the code more consistent and clearer. It
signals to other developers that the method is associated with the class rather than
with a specific instance.
Using a static field within a class
• Pay careful attention to how the constructors are constructed! Do you see now why they all call one constructor? Why? So that we
have centralized error checking of fields using our setters, and now we have an accurate count of our instances.
• Pay careful attention to lines 28, line 29, line 32and 35 in the SuperHero class!

https://onlinegdb.com/PJMCcSE4i
Inheritance in
Action …
Inheritance …
• Inheritance is a fundamental principle of OOP that allows a class (called a subclass) to inherit the fields and
methods of another class (called the superclass).
• In Java, a subclass can only inherit from one direct superclass (one parent). Class C cannot inherit from
Class A and Class B. Other Object-Oriented Programming languages may permit this, but not Java.

Class A Class B Class A

Class B
Class C
Inheritance supported by Java

NOT supported by Java Class C

• Why? Simple. Suppose Class A and Class B both have a field with the exact same name
but different data type? Or identically named methods that operate on different
parameter types or return values and behave differently. Which does Class C use? This is
why Java does not permit this.
Inheritance …
• A subclass can of have multiple subclasses of its own.
• The subclass is created using the class keyword, followed by the name of the subclass and the extends
keyword followed by the name of the superclass. The subclass inherits the fields and methods of the
superclass. The subclass can also have its own additional fields and methods.
• A subclass can only extend ONE superclass.
• The super keyword is used in the subclass to refer to the members of the superclass. This is particularly
useful when the subclass has overridden a method from the superclass and wants to call the overridden
method.
• When a subclass is instantiated, the constructor of the superclass is also called. This ensures that the fields
of the superclass are properly initialized. If the superclass doesn't have a default constructor, the subclass
constructor must explicitly call one of the constructors of the superclass using super()
• Yes, this also applies to Class level variables (static) that apply to the entire class!
Quick Demo of Inheritance
• Remember our Rectangle Class? Let’s extend that class. Let’s create another
class and call it square. 😱

Lost your Rectangle have you?


https://onlinegdb.com/ISTzuXY78

• This is … a thing of beauty. Watch this J I didn’t code any of those methods I
use here. They are inherited!
Inheritance in action …
• Does that mean that any methods I wrote in the parent Rectangle
class, I can call on a square? Yes. But there is a slight problem. Let me
show you.

• But that is easy to fix. The question is where do we fix it?


• It must be in the child class. We could override the setters, so they do not
allow the length and width of a square to get out of synch. Easily fixed. But
remember, we want no repetition of code. So, the error checking stays in the
parent class.
We could fix things like this …
• We need to code our Square class to have the following new setters:

• Attempt to change one, and both change. Plus thrown exceptions


with invalid value of -2 shown..
More inheritance …
• Many organizations have two classifications of employees – those who are paid based on
an annual salary, and those that are paid an hourly rate for the number of hours worked.
Now the fun … SalariedEmployee
HourlyEmployee Class …
Now the driver …

https://onlinegdb.com/AvBv9yJ6u
Some Practice
• A cylinder can be thought of as a circle with height. Let’s setup the necessary
classes. Let’s setup build an OOP solution to this.
• Create a base class called Circle with private double field radius. Create a constructor
which creates an instance of that object. Create public setters and getters for the field,
an equals method, and a toString() method. Create getters for area, and circumference.
• Create a subclass called cylinder which extends the base class Circle and has a field
height. Ensure that your constructor uses the constructor of the parent class as shown in
previous examples. Create a getter and setter for the height, surface area and a volume
methods. Your surface area and volume methods should use the parent class’s area
method. Override the toString() method and equals method of the parent class as well
within the child class. The metric for equality should be radii and heights are equal.
• Create a subclass called cone which extends the cylinder class. All getters and setters
including the constructors should be from one of the parent classes. The only child
methods are the constructor which uses the parent constructor (cylinder) and the
surface area and volume. These two should also use the parent classes respective
methods.
• Create a new class called Square, a child class called SquareBasedPrism.
Implement the necessary methods for area, volume. Create a child class for
square based prism called SquareBasedPyramid.
S’more Practice
• Create a parent class called Pet. What fields
should we add?
• Create three child classes Dog, Cat and Fish
each with their specific own specific fields for
those animals. J. What fields should they
have? Be creative here.
• Write a method speak() for the parent which
returns a String “this animal does not speak”.
Override the speak method in each of the
child classes to return the string ”Woof woof”
and “Meow … meow!”.
• Write code to test your classes. That includes
creating an array of each of them J
Ready for your mind to be blown?
• In Java, you can create an array of the superclass (Employee) and then
instantiate objects of the subclass (SalariedEmployee and HourlyEmployee) and
store them in the array. This is possible due to polymorphism, where objects of a
subclass can be treated as objects of their superclass.
• This way, you can have an array that can store objects of both the
SalariedEmployee and HourlyEmployee classes, treating them as instances of
their common superclass Employee.
• Look at the following code implemented here: https://onlinegdb.com/-Jjn8bEdl
• There are some drawbacks and a few issues with the employee number but
nothing that can’t be “fixed” if refactored. Perhaps removing the employee
number altogether from the Employee class and creating an Employees class
that manages the Employee objects ?? But the focus here is really that we flex
polymorphism here!
• Problem … how do we know what type of object we have within our array?
Simple. We use the instanceof operator. Let me show you:
https://onlinegdb.com/MVd_ioWeR-
Cookie Stone Returns …

Remember our simulated battle between Cookie Monster and Thanos for the Cookie
stone? Yup. I went there! Let’s examine what I have done …
VS.

https://onlinegdb.com/GC0Bph9Ocd

You might also like