Object-Oriented Programming II
Table of Contents
1 Reading
For a good overview of the OOP concepts we've covered as well as the Java syntax and terminology, read Algorithms 1.2.
2 Video
Here is a video lecture for the material outlined below. If you prefer (or want supplemental) textbook readings, I would recommend Defining Classes in Java from the Java for Python Programmers book (this covers material from Wednesday's topic as well).
The video contains sections on
- Java Packages (0:44)
- Access level (3:27)
public(4:49)private(6:48)protected(8:08)- default access level (9:14)
Circleexample v1 (9:58)static- Making a field immutable via
final(17:21) - What is an interface? (19:22)
Shapeinterface (19:58)- Class hierarchy (21:33)
extends(22:04)implements(25:57)- Class hierarchy diagram (31:58)
Circleexample v2 (32:40)
The Panopto viewer has table of contents entries for these sections: https://carleton.hosted.panopto.com/Panopto/Pages/Viewer.aspx?id=6cbfc35d-1fe2-403f-8454-aca5017ed035
3 Access Modifiers
- Background: Java packages
- A package is how Java groups together related classes
- For example, the Java package
java.langincludes various built-in classes such asStringandMath - Classes from
java.langare always available (don't need to be imported), but classes from other packages likeScannerneed to be imported in order to be used (import java.util.Scanner;)- Alternatively, you can write
java.util.Scannereverywhere and forego the import statement (not recommended)
- Alternatively, you can write
- For example, the Java package
- Packages, like classes, are also a layer of encapsulation, meaning they have the ability to hide implementation details
- A package is how Java groups together related classes
- To support abstraction, Java provides a way to specify the access level of classes, methods, and fields
- The access level determines who, if anyone, can access a particular method or field outside of the class that it's in
- Similarly with who can access a class outside of its package
- Access level is also sometimes referred to as visibility
- These access modifiers are keywords that are used
- For methods and fields:
public- Accessible to everyone with no restrictions
- The author of a class controls how users of that class will interact with it by deciding what methods will be
public - Fields should (almost never) be
public, as this exposes the class' underlying implementation (thus breaking abstraction) - Since a class'
mainmethod is how outside users run the program associated with that class, it must always bepublic
private- Only accessible in the class where they are declared
- Appropriate for fields and "helper" methods that support the functionality of
publicmethods (but don't make sense to be called directly by code using the class)
- We will likely only ever use
publicandprivatein this course, but there are two other access levels in between these two which I will include here for completeness protected- Accessible to all classes declared in the same package and any extension to the class whether in the same package or not
- default (i.e., what you get when no access modifier is given)
- Accessible to all classes declared in the same package
- Also called package-private
- To control visibility of classes within a package:
public- A class declared as
publicis visible to everyone
- A class declared as
- default (i.e., what you get when no access modifier is given)
- A class that isn't declared to be
publicis package-private, only accessible to classes declared in the same package
- A class that isn't declared to be
4 static
- A field or method can be associated with a class or with an object
- That is, it might depend on the state of a particular instance (associated with an object) or be independent of any particular instance (associated with a class)
- Let's make this concrete with an example class representing a circle
public class Circle { private double radius; public Circle(double r) { radius = r; } public double getRadius() { return radius; } public double getArea() { return radius * 3.14159265; } }
- So far this is nothing new, the field
radiusand the two accessor methods all depend on a specific instance ofCircle- These are called instance variables or instance methods
- If we want the area of a circle a radius 10, we have to write
Circle temp = new Circle(10); double area = temp.getArea();
- Now let's expand
Circlein two ways: make π a named variable we can reuse and create a method to compute the area of an arbitrary circle
public class Circle { private static double pi = 3.14159265; private double radius; public Circle(double r) { radius = r; } public double getRadius() { return radius; } public double getArea() { return radius * radius * pi; } public static double computeArea(double r) { return r * r * pi; } }
- The
statickeyword makes a field or method part of the class itself rather than a property of each class instance - This means we can invoke
Circle.computeAreato get the area of a circle with a given radius without needing to create aCircleobject:
double area = Circle.computeArea(10);
- Our field
pimust bestaticin order to be available tocomputeArea—otherwisecomputeAreawould need to create aCircleobject to access it! - One improvement we can make is to cause
pito be immutable (meaning its value can never change)- If our code is assuming
piwill always have the correct value, we should construct our code in such a way to guarantee this assumption - We can declare a variable
finalto give it this immutable property—it is not possible to modify afinalvariable after it's initializedpublic static final double PI = 3.14159265
- It's conventional to make the names of static immutable variables all caps (to set them apart as constants)
- If our code is assuming
- And now that a user of the
Circleclass can't modifyPI, we can safely make itpublic
5 Interfaces
- Interface
- A contract or template for methods a class must provide
- Intefaces don't provide any implementation themselves
- Note how in the
Shapeinterface below we useinterfaceinstead ofclass, and the method bodies are omitted
import edu.princeton.cs.algs4.Point2D; public interface Shape { public Point2D getPosition(); public void setPosition(Point2D pos); public double getArea(); }
- Class hierarchy
- A set of relationships between classes and/or interfaces
extendsrelationship- When one definition
extendsanother it inherits allpublicmethods and data - The original is said to be the supertype and the extension the subtype
- So in the example below,
Polygonwould be a subtype ofShape(andShapewould be a supertype ofPolygon) - Every
Polygonis aShape, but not everyShapeis aPolygon - The
Polygoninterface inherits all the methods fromShape, so we don't have to specify themimport edu.princeton.cs.algs4.Point2D; public interface Polygon extends Shape { public Point2D[] getVertexes(); }
- So in the example below,
- When one definition
implementsrelationship- We can make use of an interface by defining a class that
implementsit - This means the class must provide an implementation for every method specified in the interface (it won't compile otherwise)
- This means, for example, that when a class
implements Polygon, we know it has all the methods specified inShapeandPolygonimport edu.princeton.cs.algs4.Point2D; import edu.princeton.cs.algs4.StdRandom; class Rectangle implements Polygon { // instance variables private double width; private double height; private Point2D position; // constructor Rectangle(double w, double h) { width = w; height = h; position = new Point2D(StdRandom.uniform(), StdRandom.uniform()); } // accessor methods public double getWidth() { return width; } public double getHeight() { return height; } @Override public Point2D getPosition() { return position; } @Override public void setPosition(Point2D pos) { position = pos; } @Override public double getArea() { // required by Shape interface return width * height; } @Override public Point2D[] getVertexes() { // required by Polygon interface Point2D[] verts = new Point2D[4]; // clockwise starting with upper left verts[0] = new Point2D(position.x() - width / 2, position.y() - height / 2); verts[1] = new Point2D(position.x() + width / 2, position.y() - height / 2); verts[2] = new Point2D(position.x() + width / 2, position.y() + height / 2); verts[3] = new Point2D(position.x() - width / 2, position.y() + height / 2); return verts; } }
- We can make use of an interface by defining a class that
- A circle is a shape, but not a polygon, so adapting our
Circleclass from before to use an interface would meaning implementingShape:public class Circle implements Shape { private static final double PI = 3.14159265; private double radius; private Point2D position; public Circle(double r) { radius = r; position = new Point2D(StdRandom.uniform(), StdRandom.uniform()); } public double getRadius() { return radius; } @Override public Point2D getPosition() { return position; } @Override public void setPosition(Point2D pos) { position = pos; } @Override public double getArea() { return radius * radius * PI; } static double computeArea(double r) { return r * r * PI; } }
6 Practice Problems1
- Which of the following is the correct syntax to indicate that class A is a subclass of B?
public class B extends A {public class A : super B {public A(super B) {public class A extends B {public A implements B {
- Consider the following class:
// Represents a university student. public class Student { private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } public void setAge(int age) { this.age = age; } }
Also consider the following partial implementation of a subclass of
Studentto represent undergraduate students at a university:public class UndergraduateStudent extends Student { private int year; ... }
Can the code in the
UndergraduateStudentclass access thenameandagefields it inherits fromStudent? Can it call thesetAgemethod? - Consider these two classes:
public class Car { public void m1() { System.out.println("car 1"); } public void m2() { System.out.println("car 2"); } public String toString() { return "vroom"; } } public class Truck extends Car { public void m1() { System.out.println("truck 1"); } }
What is printed as a result of this code?
Car mycar = new Car(); Truck mytruck = new Truck(); System.out.println(mycar); mycar.m1(); mycar.m2(); System.out.println(mytruck); mytruck.m1(); mytruck.m2();
- Imagine that you are going to write a program to play card games. Consider a design with a
Cardclass and 52 subclasses, one for each of the unique playing cards (for example,NineOfSpadesandJackOfClubs). Is this a good design? If so, why? If not, why not, and what might be a better design? - What is the difference between implementing an interface and extending a class?
- What’s wrong with the code for the following interface? What should be changed to make a valid interface for objects that have a border color?
public interface BorderColor { private Color borderColor; public Color getBorderColor() { return borderColor; } }
7 Learning Block
- Questions?
- Get to know you, what's a place or a person from the past you'd like to visit or meet
- Form question
- Demo compiler/runtime errors
- code outside a class
- wrong main signature
- array index exception
- syntax error
- missing ;
- missing "
- missing )
- missing operator
- wrong variable name
- forgot type on declaration
- file name doesn't match class name
- wrong parameters
- forgot () on a method call
- put () on a field access
- divide by zero
- null pointer exception
- type mismatch
- Flying shapes demo
- Note that we can have an array of type
Shape[]that stores bothCircleobjects andRectangleobjects. This is called polymorphism.Shapeis a supertype of bothCircleandRectangle, and an object can always be treated as if they were an instance of their supertype. Since theShapeinterface in the flying-shapes example defines amovemethod, we can call it on objects of typeShape. - Also note on line 58 of
ShapeFuntimes.javahow we useinstanceofto check if a particular object is an instance ofPolygon(or one of its subtypes, likeRectangle), and then cast the object to aPolygonwhen passing it todrawStreamers. ShapeFuntimes.javaalso demonstrates the implementation of severalstatichelper methods that are used in bothCircleandRectangle, as well as in themainmethod.
- Note that we can have an array of type
Footnotes:
Solutions:
- (4)
public class A extends B { - The
nameandagefields are decalred to beprivate, so theUndergraduateStudentclass cannot access them. It can access thepublicsetAgemethod. - When an object is printed, it's
toStringmethod is automatically called to get the string to be printed.TruckinheritstoStringandm2fromCarand does not override either like it doesm1. Thus, it simply uses the versions oftoStringandm2defined inCar.vroom car 1 car 2 vroom truck 1 car 2
- This is not a good design because it uses separate classes to represent something that is more appropriately data within the
Cardclass (i.e., the suit and value of the card). See Bailey 7.3 (p. 155–160) for a better design. - Extending a class causes your class to inherit all methods and data from that class. Implementing an interface forces you to write your own code to implement all the methods in that interface.
- What's wrong is that interfaces can't declare fields or write bodies for methods. The following is a correct
BorderColorinterface:public interface BorderColor { public Color getBorderColor(); }