Encapsulation
10/26/2015
Hsuan-Tien Lin (林軒田) htlin@csie.ntu.edu.tw
Department of Computer Science
& Information Engineering
National Taiwan University
( 國立台灣大學資訊工程系)
Recall: Basic OOP Needs
Decompose computation into interactions of
“computing parts” called objects, each containing its own data (to be manipulated by itself) and own code (to be called by other objects)
•
designing object (what variables? what methods?)•
creating “first” object and calling its first action•
creating other objects•
calling other objects•
manipulating object status•
deleting objectsEncapsulation
Decompose computation into interactions of
“computing parts” called objects, each containing its own data (to be manipulated by itself) and own code (to be called by other objects)
•
preventing others from manipulating the object•
letting others call the allowed codeEncapsulation (1/5)
1 c l a s s Record {
2 S t r i n g name ;
3 S t r i n g password ;
4 }
5
6 p u b l i c c l a s s RecordDemo {
7 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] argv ) {
8 Record r ;
9 S t r i n g s , p ;
10 s = getLoginNameFromUser ( ) ;
11 r = getRecordFromFile ( s ) ;
12 System . o u t . p r i n t l n ( r . password ) ;
13 p = getPasswordFromUser ( ) ;
14 i f ( p . e q u a l s ( r . password ) ) {
15 / / . . .
16 }
17 }
18 }
•
if password not encoded, the SYSOP might easily get your password by getRecordFromFileEncapsulation (2/5)
1 c l a s s Record {
2 S t r i n g name ;
3 S t r i n g encoded_password ;
4 }
5
6 p u b l i c c l a s s RecordDemo {
7 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] argv ) {
8 Record r ;
9 S t r i n g s , p ;
10 s = getLoginNameFromUser ( ) ;
11 r = getRecordFromFile ( s ) ;
12 p = getPasswordFromUser ( ) ;
13 i f (YOUR_ENODING( p ) . e q u a l s ( r . encoded_password ) ) {
14 / / . . .
15 }
16 / / A new and c a r e l e s s programmer adds t h i s l i n e
17 r . encoded_password = n u l l;
18 }
19 }
•
even when password encoded, a careless programmer may make stupid bugsEncapsulation (3/5)
1 c l a s s Record {
2 p r i v a t e S t r i n g encoded_password ;
3 p u b l i c S t r i n g get_encoded_password ( ) {
4 r e t u r n encoded_password ;
5 }
6 }
7 p u b l i c c l a s s RecordDemo {
8 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] argv ) {
9 Record r ;
10 S t r i n g s , p ;
11 s = getLoginNameFromUser ( ) ;
12 r = getRecordFromFile ( s ) ;
13 p = getPasswordFromUser ( ) ;
14 i f (YOUR_ENODING( p ) . e q u a l s ( r . get_encoded_password ( ) ) ) {
15 / / . . .
16 }
17 / / A new and c a r e l e s s programmer adds t h i s l i n e
18 r . encoded_password = n u l l; / / won ’ t work
19 }
20 }
•
what if you want to set a new password?Encapsulation (4/5)
1 c l a s s Record {
2 S t r i n g name ;
3 p r i v a t e S t r i n g encoded_password ;
4 p u b l i c S t r i n g get_encoded_password ( ) {
5 r e t u r n encoded_password ;
6 }
7 p u b l i c v o i d set_encoded_password ( S t r i n g raw_password ) {
8 i f ( b l a h b l a h )
9 encoded_password = YOUR_ENCODING( raw_password ) ;
10 }
11 }
• separate implementation and use: you implement the Record
class, and other people (possibly you after two years) use it• don’t trust other people: silly mistakes can happen
• hide unnecessary details (a.k.a. instance variables)
• think about possible correct/incorrect use of your class:
check them in the methods
Encapsulation (5/5)
1 p u b l i c c l a s s RecordDemo {
2 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] argv ) {
3 Record r ;
4 S t r i n g s , p ;
5 s = getLoginNameFromUser ( ) ;
6 r = getRecordFromFile ( s ) ;
7 p = getPasswordFromUser ( ) ;
8 i f ( r . match_password ( p ) ) {
9 / / no need t o show encoding t o t h e o u t s i d e
10 }
11 r . set_encoded_password ( old_password , new_password ) ;
12 / / don ’ t want t h i s t o happen
13 r . encoded_password = n u l l;
14 }
15 }
•
freedom on making assignments: a potential hole to do bad and/or make bugsEncapsulation: Key Point
as a designer, you should avoid giving the users of your code too much freedom to do bad and/or make bugs
Hiding Variables from All Classes (1/3)
1 c l a s s Record {
2 p r i v a t e S t r i n g encoded_password ;
3 }
•
private: hiding from all classes (except myself, of course)1 c l a s s Record {
2 p r i v a t e S t r i n g encoded_password ;
3 p u b l i c boolean compare_password ( Record a n o t h e r _ r e c o r d ) {
4 r e t u r n (
5 t h i s. encoded_password ==
6 a n o t h e r _ r e c o r d . encoded_password
7 ) ;/ / okay?
8 }
9 }
Hiding Variables from All Classes (2/3)
1 c l a s s Record {
2 p r i v a t e S t r i n g name ;
3 p u b l i c S t r i n g get_name ( ) {
4 r e t u r n name ;
5 }
6 p u b l i c S t r i n g get_copied_name ( ) {
7 r e t u r n new S t r i n g ( name ) ;
8 }
9 }
•
public: accessible by all classes• accessor: get the content of the instance
Hiding Variables from All Classes (3/3)
1 c l a s s Record {
2 p r i v a t e S t r i n g name ;
3 p u b l i c v o i d set_name ( S t r i n g name ) {
4 i f ( name ! = n u l l)
5 t h i s. name = name ;
6 }
7 }
• mutator: check and set the instance variable to a value
Hiding Variables from All Classes: Key Point
private instance variables
public accessor/mutator instance methods
More on Hiding Details (1/3)
1 c l a s s Date {/ / implemented f o r your desktop
2 p r i v a t e i n t month , day ;
3 p u b l i c i n t get_month ( ) { r e t u r n month ; }
4 p u b l i c i n t get_day ( ) { r e t u r n day ; }
5 }
6 c l a s s Date_TWO {/ / implemented on a s m a l l−memory machine
7 p r i v a t e s h o r t encoded_month_and_day ;
8 p u b l i c i n t get_month ( ) {
9 r e t u r n encoded_month_and_day / 100;
10 }
11 p u b l i c i n t get_day ( ) {
12 r e t u r n encoded_month_and_day % 100;
13 }
14 }
•
two implementations, same behavior—easy for users to switch on different machines•
trade-offs: memory usage, computation, etc.More on Hiding Details (2/3)
1 c l a s s D i s t a n c e {
2 p r i v a t e double m i l e ;
3 p u b l i c double g e t _ m i l e ( ) {
4 r e t u r n m i l e ;
5 }
6 p u b l i c double get_km ( ) {
7 r e t u r n m i l e ∗ 1 . 6 ;
8 }
9 p u b l i c v o i d set_by_km (double km ) {
10 t h i s. m i l e = km / 1 . 6 ;
11 }
12 p u b l i c v o i d s e t _ b y _ m i l e (double m i l e ) {
13 t h i s. m i l e = m i l e ;
14 }
15 }
•
one storage, different information from different mutator/accessorMore on Hiding Details (3/3)
Some rules of thumb:
•
make all instance variables private•
use mutators/accessors for safely manipulate the variables Cons:•
accessing requires method calls, slower Pros:•
less chance of misuse by other users•
flexibilityMore on Hiding Details (Yet Another Case)
1 c l a s s S o l v e r {
2 p u b l i c v o i d read_in _case ( ) { }
3 p u b l i c v o i d c o m p u t e _ s o l u t i o n ( ) { }
4 p u b l i c v o i d o u t p u t _ s o l u t i o n ( ) { }
5 p u b l i c v o i d s o l v e ( ) {
6 read_in _case ( ) ;
7 c o m p u t e _ s o l u t i o n ( ) ;
8 o u t p u t _ s o l u t i o n ( ) ;
9 }
10 }
•
should the three utility functions be public?More on Hiding Details: Key Point
hiding details: don’t directly access internal stuff to gain flexibility and avoid misuse
Java Member Encapsulation (1/2)
1 c l a s s D i s t a n c e {
2 p r i v a t e double m i l e ;
3 p u b l i c double g e t _ m i l e ( ) {
4 r e t u r n m i l e ;
5 }
6 p r i v a t e double g e t _ r a t i o ( ) {
7 r e t u r n 1 . 6 ;
8 }
9 p u b l i c double get_km ( ) {
10 r e t u r n m i l e ∗ r a t i o ;
11 }
12 }
•
private: hidden, on variables and methods that you do not want anyone to see•
public: on variables and methods that you want everyone to seeJava Member Encapsulation (2/2)
1 c l a s s Demo{
2 p r i v a t e double m i l e ;
3 d e f a u l t i n t a ; / / imagine , b u t n o t c o r r e c t grammar
4 i n t b ;
5 p u b l i c double g e t _ m i l e ( ) {
6 r e t u r n m i l e ;
7 }
8 p r i v a t e double g e t _ r a t i o ( ) {
9 r e t u r n 1 . 6 ;
10 }
11 double get_km ( ) {
12 r e t u r n m i l e ∗ r a t i o ;
13 }
14 }
15 c l a s s Another {
16 v o i d l a l a l a ( ) { i n t l u l u = new Demo ( ) . b + 1 ; }
17 }
•
default: classes in the same source file (et al.) can access it•
a “gray-area” usageJava Member Encapsulation: Key Point
•
public/private:the more common pair for OO programmers
•
default:for laziness of beginners, or real-advanced use (later)