Object-Oriented Programming 95-712

52
Object-Oriented Object-Oriented Programming Programming 95-712 95-712 MISM/MSIT MISM/MSIT Carnegie Mellon Carnegie Mellon University University Lecture 4: Access Control Lecture 4: Access Control & Reuse & Reuse

description

Object-Oriented Programming 95-712. MISM/MSIT Carnegie Mellon University Lecture 4: Access Control & Reuse. Today’s Topics. Implementation hiding with packages and access specifiers. Composition Inheritance More on constructors Finals Class loading. Access Specifiers. - PowerPoint PPT Presentation

Transcript of Object-Oriented Programming 95-712

Object-Oriented ProgrammingObject-Oriented Programming95-71295-712

MISM/MSITMISM/MSIT

Carnegie Mellon UniversityCarnegie Mellon University

Lecture 4: Access Control & ReuseLecture 4: Access Control & Reuse

Today’s TopicsToday’s Topics

Implementation hiding with packages and Implementation hiding with packages and access specifiers.access specifiers.

CompositionComposition InheritanceInheritance More on constructorsMore on constructors FinalsFinals Class loadingClass loading

Access SpecifiersAccess Specifiers

publicpublic, , protectedprotected, , privateprivate and “friendly” and “friendly” We haven’t used these yet, except for We haven’t used these yet, except for

main()main() and and toString()toString().. main()main() needs to be needs to be publicpublic, so the runtime , so the runtime

system can call it.system can call it. toString()toString() needs to be needs to be publicpublic since it is since it is

publicpublic in in ObjectObject, and we are “overlaoding” , and we are “overlaoding” it.it.

The “Need To Know” PrincipleThe “Need To Know” Principle

Like military secrets, portions of your Like military secrets, portions of your classes are best kept private.classes are best kept private.

The public interface of a class should The public interface of a class should provide everything users need, but nothing provide everything users need, but nothing they don’t.they don’t.

Access specifiers allow you to enforce the Access specifiers allow you to enforce the “need to know” principle.“need to know” principle.

Access SpecifiersAccess Specifiers

publicpublic members (variables and methods) members (variables and methods) are freely available for anyone’s use.are freely available for anyone’s use.

privateprivate members can be accessed (used) members can be accessed (used) only by the methods of the containing class.only by the methods of the containing class.

protectedprotected members are public to members are public to subclasses, private to others.subclasses, private to others.

““Friendly” members have Friendly” members have package accesspackage access::– no access specifierno access specifier– public within the containing packagepublic within the containing package

PackagesPackages

Java’s concept of “module”.Java’s concept of “module”. A group of related classes.A group of related classes. A package can have a name, but there is the A package can have a name, but there is the

unnamed package, which holds all the unnamed package, which holds all the classes in your program that you haven’t classes in your program that you haven’t put into a named package.put into a named package.

How Does It All Work?How Does It All Work?

So far, we haven’t used packages and So far, we haven’t used packages and access specifiers. Why has this worked?access specifiers. Why has this worked?– We kept all our We kept all our .class.class files in the same folder; files in the same folder;

they are in the unnamed package.they are in the unnamed package.– All of our members were therefore friendly.All of our members were therefore friendly.– Only methods that are called from another Only methods that are called from another

package need access specifiers.package need access specifiers.– Running outside of Together: make sure you Running outside of Together: make sure you

have the current directory (‘.’) in your have the current directory (‘.’) in your classpath.classpath.

The Basic RulesThe Basic Rules

Class members should be Class members should be privateprivate unless unless there is a need to know or use.there is a need to know or use.

Think carefully about the public interface.Think carefully about the public interface. Use accessors/mutators (aka get and set Use accessors/mutators (aka get and set

methods) to control access to private methods) to control access to private member variables.member variables.

Often we create methods that are only used Often we create methods that are only used internally; make these internally; make these privateprivate..

We’ll worry about We’ll worry about protectedprotected later. later.

ExampleExample

public class Fraction {public Fraction() public Fraction(int n, int d) public String toString()  public String toDecimal()  public Fraction add(Fraction f)private int numerator;private int denominator;private int gcd(int a, int b)

}

How To Change A How To Change A FractionFraction??

This is a design decision.This is a design decision. Some classes are “immutable” for good (or Some classes are “immutable” for good (or

bad!) reasons. bad!) reasons. StringString is an example. is an example. If we want users to change a If we want users to change a FractionFraction

object’s values, provide a “set” function:object’s values, provide a “set” function:public void set(int n, int d) { // test carefully for suitability, then: numerator = n; denominator = d;}

Interface vs. ImplementationInterface vs. Implementation

For flexibility, we want the right to change For flexibility, we want the right to change an implementation if we find a better one.an implementation if we find a better one.

But we don’t want to break client code.But we don’t want to break client code. Access specifiers restrict what clients can Access specifiers restrict what clients can

rely on.rely on. Everything marked private is subject to Everything marked private is subject to

change.change.

Example: Example: NNCollectionNNCollection

Our clients want to store last names and Our clients want to store last names and associated telephone numbers.associated telephone numbers.

The list may be large.The list may be large. They wantThey want

– a class NameNumber for name & number pairsa class NameNumber for name & number pairs– NNCollection()NNCollection()– insert(NameNumber)insert(NameNumber)– findNumber(String)findNumber(String)

NameNumberNameNumberpublic class NameNumber { private String lastName; private String telNumber; public NameNumber() {} public NameNumber(String name, String num) { lastName = name; telNumber = num; } public String getLastName() { return lastName; } public String getTelNumber() { return telNumber; }}

NNCollectionNNCollectionpublic class NNCollection { private NameNumber[] nnArray = new NameNumber[100]; private int free; public NNCollection() {free = 0;} public void insert(NameNumber n) { int index = 0; for (int i = free++; i != 0 && nnArray[i-1].getLastName().compareTo(n.getLastName()) > 0; i--) { nnArray[i] = nnArray[i-1]; index = i; } nnArray[index] = n; }

NNCollection (cont.)NNCollection (cont.)

public String findNumber(String lName) { for (int i = 0; i != free; i++) if (nnArray[i].getLastName().equals(lName)) return nnArray[i].getTelNumber(); return new String("Name not found"); }}

NNCollectionNNCollection Insertion Insertion

nnArray…

Initial Array

free

nnArray…

Insert “Lewis”

free

Lewis268-1234

NNCollectionNNCollection Insertion (cont.) Insertion (cont.)

nnArray…

i

Lewis268-1234

Insert “Clay”

free

nnArray…

i

Lewis268-1234

free

nnArray…Clay268-5678

free

Lewis268-1234

12

34

5

Yes, This Is RottenYes, This Is Rotten

It uses a fixed-size array.It uses a fixed-size array. Array elements are interchanged every time Array elements are interchanged every time

a new name is entered. Slow.a new name is entered. Slow. The array is searched sequentially. Slow.The array is searched sequentially. Slow. But, our clients can get started on But, our clients can get started on theirtheir

code.code. We go back and build a better We go back and build a better

implementation.implementation.

Better Better NNCollectionNNCollection

Use a Use a binary treebinary tree.. Names “on the left” precede Names “on the left” precede

lexicographically.lexicographically. Roughly logarithmic insert and retrieve Roughly logarithmic insert and retrieve

times.times. Very recursive, but not very expensive.Very recursive, but not very expensive.

Binary Tree LayoutBinary Tree Layout

NNCollection root NNTreeLewis

Clay

Beggs Day Martin null

Moore

nullnull null null null null

lChild rChild

Note: Only the name of the NameNumber object is shown

NNTreeNNTree Class Class

Each Each NNTreeNNTree object object – is a node, holding a is a node, holding a NameNumberNameNumber object. object.– keeps a reference to its left child and right keeps a reference to its left child and right

child.child.– knows how to insert a knows how to insert a NameNumberNameNumber object. object.– knows how to find a knows how to find a NameNumberNameNumber object. object.

Inserting “McCoy”Inserting “McCoy”

NNCollection Lewis

Clay

Beggs Day Martin null

Moore

nullnull null null null null

McCoy > Lewis

McCoy < Moore

McCoy > Martin

Inserting “McCoy”Inserting “McCoy”

NNCollection Lewis

Clay

Beggs Day Martin null

Moore

nullnull null null null

McCoy > Lewis

McCoy < Moore

McCoy > Martin

McCoy

null null

Finding “Day”Finding “Day”

NNCollection Lewis

Clay

Beggs Day Martin null

Moore

nullnull null null null McCoy

null null

Day < Lewis

Day > Clay

NNTreeNNTree Class Definition Class Definition

public class NNTree { private NNTree lChild; private NNTree rChild; private NameNumber contents; public NNTree(NameNumber n) { contents = n; }

NNTreeNNTree Class Definition (cont.) Class Definition (cont.)

public void insert(NameNumber n) { if (n.getLastName().compareTo(contents.getLastName()) < 0) if (lChild != null) lChild.insert(n); else lChild = new NNTree(n); else if (rChild != null) rChild.insert(n); else rChild = new NNTree(n);}

NNTreeNNTree Class Definition (cont.) Class Definition (cont.)

public String findNumber(String lName) { if (lName.compareTo(contents.getLastName()) < 0) if (lChild != null) return lChild.findNumber(lName); else return new String("Name not found"); else if (lName.equals(contents.getLastName())) return contents.getTelNumber(); else if (lName.compareTo(contents.getLastName()) > 0) if (rChild != null) return rChild.findNumber(lName); else return new String("Name not found"); else return new String("Name not found"); }

NNCollectionNNCollection Again Againpublic class NNCollection { private NNTree root; public SortedCollection2() {} public void insert(NameNumber n) { if (root != null) root.insert(n); else root = new NNTree(n); } String findNumber(String lName) { if (root != null) return root.findNumber(lName); else return new String("Name not found"); }}

More on PackagesMore on Packages

Bringing in a package of classes:Bringing in a package of classes:import java.util.*;import java.util.*;

Bringing in a single class:Bringing in a single class:import java.util.ArrayList;import java.util.ArrayList;

The compiler can find these things, through the The compiler can find these things, through the classpath.classpath.

Together projects supply a standard classpath.Together projects supply a standard classpath. If we’re working from the command line, the If we’re working from the command line, the

classpath must be an environmental variable.classpath must be an environmental variable.

Creating a PackageCreating a Package

The very first line in all the files intended The very first line in all the files intended for the package named for the package named myPackagemyPackage::package myPackage;package myPackage;

Put all of the .class files in a directory Put all of the .class files in a directory named named myPackagemyPackage..

Put the Put the myPackagemyPackage directory, as a directory, as a subdirectory, in a directory given in the subdirectory, in a directory given in the classpath.classpath.

Class AccessClass Access

Classes can be Classes can be publicpublic or not. or not. Non-Non-publicpublic classes are available only classes are available only

within the package they are defined in.within the package they are defined in. There can be only one There can be only one publicpublic class in a class in a

“compilation unit” (a .java file).“compilation unit” (a .java file). Non-Non-publicpublic classes are “helper” classes, not classes are “helper” classes, not

for public use.for public use.

Class ReuseClass Reuse

A noble goal, and in Java it’s finally A noble goal, and in Java it’s finally happening!happening!

Basically two ways: Basically two ways: compositioncomposition and and inheritanceinheritance..

Composition is called “has-a”.Composition is called “has-a”. Inheritance is called “is-a”.Inheritance is called “is-a”.

CompositionComposition

We’ve done plenty of this already:We’ve done plenty of this already:– The Monte The Monte GameGame class is composed of several class is composed of several

DoorDoors (among other things).s (among other things).– The Monte The Monte PlayManyGamesPlayManyGames class has-a class has-a

GameGame.. All you do is place a reference to a different All you do is place a reference to a different

kind of object in your class: Ta Da! You’re kind of object in your class: Ta Da! You’re using composition.using composition.

InheritanceInheritance

An object of a new class that An object of a new class that inheritsinherits from from an existing class has all the “powers and an existing class has all the “powers and abilities” of the parent class:abilities” of the parent class:– all data membersall data members– all methodsall methods– you can add additional data and methods if you you can add additional data and methods if you

wishwish– a derived class object “is-an” object of the a derived class object “is-an” object of the

parent class type, so can be used in function parent class type, so can be used in function calls where a parent-class object is specifiedcalls where a parent-class object is specified

Inheritance SyntaxInheritance Syntaxclass Cleanser { private String activeIngredient; public void dilute(int percent) {// water-down} public void apply(DirtyThing d) {// pour it on} public void scrub(Brush b) {// watch it work}}public class Detergent extends Cleanser { private String specialIngredient; public void scrub(Brush b) { // scrub gently, then super.scrub(b); // the usual way } public void foam() { // make bubbles}}

Access Control, AgainAccess Control, Again

DetergentDetergent does indeed have an does indeed have an activeIngredientactiveIngredient, but it’s not accessible., but it’s not accessible.

If If DetergentDetergent need to access it, it must be need to access it, it must be eithereither– made made protected protected (or friendly) in (or friendly) in CleanserCleanser, or, or– be accessible through get and set methods in be accessible through get and set methods in

CleanserCleanser.. You can’t inherit just to get access!You can’t inherit just to get access!

What Is A What Is A Detergent Detergent Object?Object?

An object of type An object of type CleanserCleanser, having all the , having all the members of members of CleanserCleanser..

An object of type An object of type DetergentDetergent, having all the , having all the additional members of additional members of DetergentDetergent..

An object that “responds” to “messages” An object that “responds” to “messages” (ummm…method calls) as though it’s a (ummm…method calls) as though it’s a CleanserCleanser, unless, unless– new methods have been added to new methods have been added to DetergentDetergent, or, or– CleanserCleanser methods have been over-ridden. methods have been over-ridden.

Subclasses and ConstructorsSubclasses and Constructors

Think of a Think of a DetergentDetergent object as containing a object as containing a CleanserCleanser sub-objectsub-object..

So, that sub-object has to be constructed So, that sub-object has to be constructed when you create a when you create a DetergentDetergent object. object.

The The CleanserCleanser object has to be created object has to be created firstfirst, , since constructing the remaining since constructing the remaining DetergentDetergent part might rely on it.part might rely on it.

““Always call the base class constructor Always call the base class constructor first.”first.”

Subclasses and ConstructorsSubclasses and Constructorsclass Cleanser { private String activeIngredient; Cleanser() { System.out.println(“Cleanser constructor”); }}public class Detergent extends Cleanser { private String specialIngredient; Detergent() { System.out.println(“Detergent constructor”); } public static void main(String[] args) { Detergent d = new Detergent(); } }

Subclasses and ConstructorsSubclasses and Constructorsclass Cleanser { private String activeIngredient; Cleanser(String active) { activeIngredient = active; }}public class Detergent extends Cleanser { private String specialIngredient; Detergent(String active, String special) { super(active); // what if this isn’t here? specialIngredient = special; }}

Composition vs. InheritanceComposition vs. Inheritance

Think “has-a” vs. “is-a”.Think “has-a” vs. “is-a”. Consider the Consider the SortedCollectionSortedCollection class. class.

Suppose now we need to store a Suppose now we need to store a String/intString/int pair (names and ages, perhaps).pair (names and ages, perhaps).

Should we inherit, or compose?Should we inherit, or compose? In either approach, we just need to be able In either approach, we just need to be able

to turn to turn StringStrings into s into intints, and vice versa (not s, and vice versa (not hard).hard).

Composition vs. InheritanceComposition vs. Inheritanceclass NACollection { private NNCollection nnc; NACollection() { // …} public void insert (NameAge n) { uses nnc’s insert()} public int findAge(String name) { uses nnc’s findNumber()}}

or

class NACollection extends NNCollection { NACollection() { //…} public void insert(NameAge n) { uses super.insert()} public int findAge(String name) { uses super.findNumber()}}

protectedprotected Class Members Class Members

publicpublic to subclasses. to subclasses. privateprivate to “the outside world”, to “the outside world”, except within the package (i.e., they are except within the package (i.e., they are

“friendly”.“friendly”. privateprivate is usually the best policy, unless is usually the best policy, unless

you are looking for speed (but then why use you are looking for speed (but then why use Java!?).Java!?).

UpcastingUpcastingclass CellPhone { cellPhone() { //…} public void ring(Tune t) { t.play(); }}class Tune { Tune() { // …} public void play() { // …}}class ObnoxiousTune { ObnoxiousTune() { // …} // …}

An ObnoxiousTune “is-a” Tune

class DisruptLecture { public static void main() { CellPhone noiseMaker = new CellPhone(); ObnoxiousTune ot = new ObnoxiousTune(); noiseMaker.ring(t); // ot works though Tune called for }}

Tune

ObnoxiousTune

A “UML” diagram

The The finalfinal Keyword Keyword

Vaguely like Vaguely like constconst in C++. in C++. It says “this is invariant”.It says “this is invariant”. Can be used forCan be used for

– datadata– methodsmethods– classesclasses

A kind of protection mechanism.A kind of protection mechanism.

finalfinal Data (Compile-Time) Data (Compile-Time)

For primitive types (For primitive types (intint, , floatfloat, etc.), the , etc.), the meaning is “this can’t change value”.meaning is “this can’t change value”.class Sedan {class Sedan {

final int numDoors = 4;final int numDoors = 4; For references, the meaning is “this For references, the meaning is “this

reference must always refer to the same reference must always refer to the same object”.object”. final Engine e = new Engine(300);final Engine e = new Engine(300);

finalfinal Data (Run-Time) Data (Run-Time)

Called a “blank final;” the value is filled in Called a “blank final;” the value is filled in during execution.during execution.class Sedan { final int topSpeed; Sedan(int ts) { topSpeed = ts; // … }}class DragRace { Sedan chevy = new Sedan(120), ford = new Sedan(140); //! chevy.topSpeed = 150;

finalfinal Method Arguments Method Arguments

Same idea:Same idea:– a a finalfinal primitive has a constant value primitive has a constant value– a a finalfinal reference always refers to the same reference always refers to the same

object.object. Note well: a Note well: a finalfinal reference does reference does notnot say say

that the object that the object referred toreferred to can’t change ( can’t change (cf.cf. C++)C++)

finalfinal Methods Methods

finalfinal methods cannot be overridden in methods cannot be overridden in subclasses. Maybe a bad idea?subclasses. Maybe a bad idea?

finalfinal methods can be inlined, allowing the methods can be inlined, allowing the compiler to insert the method code where it compiler to insert the method code where it is called.is called.

This may improve execution speed.This may improve execution speed. Only useful for small methods.Only useful for small methods. privateprivate methods are implicitly methods are implicitly finalfinal..

finalfinal Classes Classes

These can’t be inherited from (ummm, These can’t be inherited from (ummm, “subclassed”?.“subclassed”?.

All methods are implicitly All methods are implicitly finalfinal, so inlining , so inlining can be done.can be done.

Class LoadingClass Loading

A A .class.class file is loaded when file is loaded when– the first object of that type is created, orthe first object of that type is created, or– when a static member is first used.when a static member is first used.

When a derived class object is created, the When a derived class object is created, the base class file is immediately loaded (before base class file is immediately loaded (before the derived class constructor actually goes the derived class constructor actually goes to work).to work).