← Back to Week 5

Has-A Relationship

When one class contains instances of another, that's a has-a relationship. Hand has-a Card. Deck has-a Card. But Hand doesn't care that Deck exists.

Card - suit: String - value: String - isFaceUp: boolean + flip() Hand - cards: ArrayList<Card> + deal(Card) + getValue() + getSize() Deck - cards: ArrayList<Card> + shuffle() + deal(): Card + getSize() has-a has-a no direct dependency
Watch Deck.deal() → Hand.deal(card)
Deck
Hand
// In MainApp.java
Card card = deck.deal(); // Deck pulls a Card off the top
hand.deal(card); // Hand stores it in its ArrayList<Card>
Two has-a relationships, one shared class. Both Hand and Deck have an ArrayList<Card> field. Neither has any reference to the other — main is the one that tells them to talk. That's loose coupling at work: two classes can collaborate without knowing about each other.
Coupling — the partner concept to cohesion
Loose vs Tight Coupling
Cohesion is about within a class — how related the parts are. Coupling is about between classes — how dependent they are on each other. Aim for loose coupling. The card-game setup above already shows it — here's what would happen if it slipped.
✓ Loose (this is what we built)
Hand and Deck stay independent
Hand Deck Card has-a has-a
Hand and Deck both depend on Card — that's fine, Card is a building block. But neither holds a reference to the other. Change Deck's shuffle algorithm, and Hand doesn't notice.
✕ Tight (avoid this)
Hand reaches into Deck directly
Hand Deck Card has-a has-a knows about
Now Hand stores a Deck field and calls deck.deal() itself. Any change to Deck can break Hand. Tests get harder — you can't test Hand without also building a Deck.
← Static Classes Class Communication Walkthrough →