Title: Objects and Encapsulation
1Objects and Encapsulation
(incomplete) James Brucker
2Why Encapsulation?
- Encapsulation means that an object contains both
data and methods to operate on the data. - An object encapsulates its data (state).
- Responsibility an object is responsible for its
own data - Benefit of Encapsulation
- Enables you to change implementation without
affecting other objects. - To enforce this, an object usually declares its
data members (attributes) to be protected or
private. - This practice is called data hiding.
- You can hide behavior, too -- methods can be
private.
3Why Encapsulation?
- Encapsulation means that an object contains both
data and methods to operate on the data. - An object encapsulates its data (state).
- Responsibility an object is responsible for its
own data - Benefit of Encapsulation
- You to change the implementation without
affecting other classes. - Enforce data integrity a class's mutator method
can check for valid data before saving it. - Makes programs easier to test and maintain.
4Person class
public class Person private String
name private Date birthday / create a new
person / public Person( String name, Date
birthday ) this.name name this.birthday
birthday / accessor but no mutator
methods / public String getName() return
name public Date getBirthday() return
birthday
5Person class modified
Public methods don't change, only the internal
format of data changes.
public class Person private String
name private Calendar birthday / create a
new person / public Person( String name, Date
date ) this.name name this.birthday
new Calendar() this.birthday.setTime( date
) / accessor but no mutator methods /
public String getName() return name public
Date getBirthday() return
birthday.getTime() // creates a Date
6Mutability and Encapsulation
public class Person private String
name private Date birthday / create a new
person / public Person( String name, Date
birthday ) this.name name this.birthday
birthday / accessor but no mutator
methods / public String getName() return
name public Date getBirthday() return
birthday
Can you change a peron's name or birthday?.
7Mutability and Encapsulation
public class Person private String
name private Date birthday / create a new
person / public Person( String name, Date
birthday ) this.name name this.birthday
birthday / accessor but no mutator
methods / public String getName() return
name public Date getBirthday() return
birthday
Can you change a peron's name or birthday?.
8Breaking Encapsulation
- Can you change a Person's name (after creating
object)? - Can you change the Person's birthday (after
creating object)?
Date bday new Date( 98, 1, 15 ) // Feb
15,1998 Person pee new Person( "Joe", bday )
pee.getName().toUpperCase()
pee.getBirthday().setMonth( 11 )
System.out.println( pee.getName() )
System.out.println( pee.getBirthday() )
bday.setYear( 0 ) System.out.println(
pee.getBirthday() )
1
2
9Mutable and Immutable Objects
- Mutable attributes of object can be changed
after object is created. - Immutable attributes of object cannot be changed
after object is created.
10Mutable and Immutable Objects
- Which types are mutable? Which are immutable?
- String s new String( "Hello" ) s.toUpperCase()
- Integer n new Integer( 10 ) n
- Date d new Date( ) d.setMonth( 0 )
- StringBuffer sb new StringBuffer()
- sb.append("more")
Use BlueJ codepad to try this. Create 2
references to same object.
11Immutable Objects
private String name / accessor method for
name / public String getName( ) return
name
- this does not break encapsulation of Person even
though it gives the caller a reference to the
name of Person. - Why?
- Because String objects are immutable.
12Test Yourself (1)
public class Person private StringBuffer
address // use Stringbuffer / accessor
method for address. / public StringBuffer
getAddress( ) return address
- does this break the encapsulation of the
(private) address ?
13Fixing Encapsulation
- Accessor methods for mutable objects should
always return a copy of the object, or an
immutable form of the object. - Return a copy
public StringBuffer getAddress( ) // return
a copy of the address return new
StringBuffer(address)
- convert to a String (immutable and also a copy)
public String getAddress( ) // return String
form of address return address.toString()
14Constructor can break encapsulation
- Does this constructor violate encapsulation of
the private birthday attribute?
public class Person private String name //
person's name private Date birthday // person's
birthday / constructor for a new Person
/ public Person( String name, Date date )
this.name name this.birthday date
public Date getBirthday( ) return
birthday
15Constructor can break encapsulation
- Does this constructor violate encapsulation of
the private birthday attribute?
public class Person private String name //
person's name private Date birthday // person's
birthday / constructor for a new Person
/ public Person( String name, Date date )
this.name name this.birthday
date.clone() public Date getBirthday( )
return birthday.clone()
16Constructor (2)
name "Ae Naresuan" date new Date(60, 2,
1) ae new Person(name,date)
name
reference
date
reference
public class Person Person(String aname,
Date date) this.name aname this.birthday
date
String "Ae Naresuan"
Date year 60 month 2 day 1 seconds 0
What does the constructor do?
17Constructor (3)
name "Ae Naresuan" date new Date(60, 2,
1) ae new Person(name,date)
name
reference
date
reference
public class Person Person(String aname,
Date date) this.name aname this.birthday
date
aePerson name String birthday Date
String "Ae Naresuan"
Date year 60 month 2 day 1 seconds 0
Constructor sets the attributes to refer to the
same objects as the parameters.
18Constructor (4)
// change the date date.setYear(80) date.setMonth
(11)
name
reference
date
reference
The "ae" Person object refers to the same Date
object as the caller. Any changes in date also
change ae's birthday.
aePerson name String birthday Date
String "Ae Naresuan"
Date year 80 month 11 day 1 seconds 0
19Constructor (5)
- Let's create a couple of people
public void dateTest() // Ae is born in March
1, 1960 Date date new Date(60,Calendar.MARCH,
1) Person ae new Person("Ae Naresuan",
date) // Be is born on April 20, 1960 // I'm
too lazy to make a new date object... date.setMon
th(Calendar.APRIL) date.setDate(20) Person be
new Person("Be Careful", date) // when was
Ae born? System.out.println("Ae's birthday is
" ae.getBirthday().toString() )
20Constructor how to fix
- Constructor should create a copy of any mutable
objects.
public class Person private String name //
person's name private Date birthday // person's
birthday / constructor for a new Person
/ public Person( String aname, Date date )
this.name aname // the Date class
implements Cloneable this.birthday
date.clone( )
21Sometimes We Want Mutable Components
22Bank Account
- We want the Person data in Bank Account to change
when Person updates his address, telephone, etc.
owner
23Breaking Encapsulation by Mutable Components
24Example Transaction
- KUCoupon has a Transaction class that saves an
array of coupons
public class Transaction private Integer
coupons public Integer getCoupons( )
return coupons // return array //
constructor public Transaction( Integer
coupons ) this.coupons coupons
25Example Transaction (2)
- KUCoupon has a Transaction class that saves an
array of coupons
// use autoboxing to convert int to
Integer Integer x new Integer 1, 2, 3
Transaction transaction new Transaction( x
) x1 15 Integer y
trans.getCoupons( ) y2 20
1. Does this change the coupons1 in transaction
?
2. Does this change the coupons2 in transaction
?
26The Cause
- An array is a mutable object.
27The Solution
- Make a copy of mutable objects.
public class Transaction private int
coupons public int getCoupons( ) return
java.util.Arrays.copyOf( coupons,
coupons.length )// return copy //
constructor - copy the parameter public
Transaction( int c ) this.coupons
Arrays.copyOf( c, c.length )
28This May Not Be Efficient
- Making a copy of a large array uses memory and
time. - In some application, you may not want to do this.