|
|
Suppose we made the data fields in the Card class public:
public class Card { public String suit; public String rank; Card(...) // Constructor to create a Card< object { ... } } |
This will allow programmers to write code that uses the data field directly:
public class Card { public String suit; public String rank; Card(...) // Constructor to create a Card< object { ... } } |
Then changing the implementation of the Card class will cause errors in the user program:
public class Card { public int suit; // 0="Spades", 1="Hearts", 2="Diamonds", 3="Clubs" public String rank; Card(...) // Constructor to create a Card< object { ... } } |
Data field encapsulation requires that data fields are defined as private
public class Card { private String suit; private String rank; Card(...) // Constructor to create a Card< object { ... } public String getSuit() { return suit; } public void setSuit(String newSuit) { suit = newSuit; } } |
$64,000 question: how can other classes use/access these data fields ?
When other classes needs to read a data field, we must provide a (public) accessor method:
public class Card { private String suit; private String rank; Card(...) // Constructor to create a Card< object { ... } public String getSuit() // Accessor or "getter" method { return suit; } public void setSuit(String newSuit) { suit = newSuit; } } |
When other classes needs to read a data field, we must provide a (public) mutator method:
public class Card { private String suit; private String rank; Card(...) // Constructor to create a Card< object { ... } public String getSuit() // Accessor or "getter" method { return suit; } public void setSuit(String newSuit) // Mutator or "setter" method { suit = newSuit; } } |
How will this help ???
Suppose we made the data fields in the Card class private:
public class Card { private String suit; private String rank; Card(...) { ... } // Constructor to create a Card< object public String getSuit() // Accessor method { return suit; } } |
Then: other classes must use an accessor/mutator method to access a data field:
public class Card { private String suit; private String rank; Card(...) { ... } // Constructor to create a Card< object public String getSuit() // Accessor method { return suit; } } |
Suppose we want to change the implementaion of the Card object:
public class Card { private int suit; // 0="Spades", 1="Hearts", 2="Diamonds", 3="Clubs" private String rank; Card(...) { ... } // Constructor to create a Card< object public String getSuit() // Accessor method { return suit; } } |
We can maintain compatibility by also update the accessor/mutator methods:
public class Card { private int suit; // 0="Spades", 1="Hearts", 2="Diamonds", 3="Clubs" private String rank; Card(...) { ... } // Constructor to create a Card< object public String getSuit() // Accessor method { String[] suitToString = {"Spades", "Hearts", "Diamonds", "Clubs"}; return suitToString[suit]; // Translates number to string ! } } |
Result: all classes that use the Card class will still work correctly:
public class Card { private int suit; // 0="Spades", 1="Hearts", 2="Diamonds", 3="Clubs" private String rank; Card(...) { ... } // Constructor to create a Card< object public String getSuit() // Accessor method { String[] suitToString = {"Spades", "Hearts", "Diamonds", "Clubs"}; return suitToString[suit]; // Translates number to string ! } } |
DEMO: demo/03-classes/19-encapsulation/ORIG + SOLUTION
|