Effective Java: Classes and Interfaces - PowerPoint PPT Presentation

1 / 26
About This Presentation
Title:

Effective Java: Classes and Interfaces

Description:

Cover Items 16 through 20. Part of 'Classes and ... superclass to maintain invariants in face of malicious/careless subclass ... the code. Sub s ... – PowerPoint PPT presentation

Number of Views:62
Avg rating:3.0/5.0
Slides: 27
Provided by: richardb45
Category:

less

Transcript and Presenter's Notes

Title: Effective Java: Classes and Interfaces


1
Effective Java Classes and Interfaces
  • Last Updated Fall 2008
  • SWE 332

2
Agenda
  • Material From Joshua Bloch
  • Effective Java Programming Language Guide
  • Cover Items 16 through 20
  • Part of Classes and Interfaces Chapter
  • Was Items 14 through 18 in 1st Edition
  • Moral
  • Inheritance requires careful programming

3
Item 16 Favor Composition over Inheritance
  • Issue ONLY for implementation inheritance
  • Interface inheritance does NOT have these
    problems
  • Inheritance breaks encapsulation!
  • Difficult to evolve superclass without breaking
    subclasses
  • Difficult for superclass to maintain invariants
    in face of malicious/careless subclass

4
Example Broken Subtype
  • public class IHashSetltEgt extends HashSetltEgt
  • private int addCount 0 // add() calls
  • public IHashSet()
  • public IHashSet(Collectionlt? extends Egt c)
  • super(c)
  • public boolean add(E o)
  • addCount return super.add(o)
  • public boolean addAll(Collectionlt? extends Egt
    c)
  • addCount c.size() return
    super.addAll(c)

5
Broken Example, continued
  • So, whats the problem?
  • IHashSetltStringgt s new IHashSetltStringgt()
  • s.addAll(Arrays.asList(Snap, Crackle,
    Pop))
  • What does addCount() return?
  • 3?
  • 6?
  • Internally, HashSets addAll() is implemented on
    top of add(), which is overridden. Note that
    this is an implementation detail, so we cant get
    it right in IHashSet

6
Source of Difficulty Overridden Methods
  • Overriding methods can be tricky
  • May break the superclass invariant
  • Overridden method does not maintain invariant
  • May break subclass invariant
  • New methods may be added to superclass
  • What if new method matches subclass method?
  • Also, recall problems with equals() and hashCode()

7
Composition
  • Fortunately, composition solves all of these
    problems even though it makes the programmer
    work harder
  • // Inheritance
  • public Class Foo extends Fie
  • // Composition
  • public class Foo
  • private Fie f
  • // Note forwarded methods

8
Revisiting the Example
  • public class ISetltEgt implements SetltEgt
  • private final SetltEgt s
  • private int addCount 0
  • public ISet (SetltEgt s) this.s s
  • public boolean add(E o)
  • addCount return s.add(o)
  • public boolean addAll (Collectionlt? extends Egt
    c)
  • addCount c.size()
  • return s.addAll(c)
  • // forwarded methods from Set interface

9
This is Cool!
  • Consider temporarily instrumenting a Set
  • Note that Set is an interface
  • static void f(SetltDoggt s)
  • ISet myS new ISetltDoggt (s)
  • // use myS instead of s
  • // all changes are reflected in s!

10
A Variation That Doesnt Work
  • public class ICollectionltEgt implements
    CollectionltEgt
  • private final CollectionltEgt c
  • private int addCount 0
  • public ICollection (CollectionltEgt c) this.c
    c
  • public boolean add(E o)
  • public boolean addAll (Collectionlt? extends Egt
    c)
  • // forwarded methods from Collection interface
  • public boolean equals(Object o)
  • return c.equals(o) // Now, were
    dead!

11
This is no longer Cool!
  • Consider temporarily instrumenting a Set
  • Note Set is a subtype of Collection
  • SetltDoggt s new HashSetltDoggt()
  • ICollectionltDoggt t new ICollectionltDoggt(s)
  • s.equals(t) // c is not a Set, so false
  • t.equals(s) // t.c s, so true
  • Issue Set has a uniform equals contract
    Collection does not (and should not)
  • Keep this in mind when using this model.

12
Item 17 Design and Document for Inheritance
  • Or else prohibit it.
  • First, document effects of overriding any method
  • Document self use, as in IHashSet example
  • This is implementation detail, but unavoidable,
    since subclass sees implementation.
  • Inheritance violates encapsulation!

13
Efficiency May Require Hooks
  • protected methods may be required for efficient
    subclasses.
  • Example
  • protected removeRange() method in AbstractList
  • Not of interest to List clients
  • Only of interest to implementers of AbstractList
    provides fast clear() operation
  • Alternative O(n2) clear operation

14
Inheritance is Forever
  • A commitment to allow inheritance is part of
    public API
  • If you provide a poor interface, you (and all of
    the subclasses) are stuck with it.
  • You cannot change the interface in subsequent
    releases.
  • TEST for inheritance by writing subclasses

15
Constructors Must Not Invoke Overridable Methods
  • // Problem constructor invokes overridden m()
  • public class Super
  • public Super() m()
  • public void m()
  • public class Sub extends Super
  • private final Date date
  • public Sub() date new Date()
  • public void m() // access date variable

16
What Is the Problem?
  • Consider the code
  • Sub s new Sub()
  • The first thing that happens in Sub() constructor
    is a call to constructor in Super()
  • The call to m() in Super() is overridden
  • But date variable is not yet initialized!
  • Further, initialization in Super m() never
    happens!
  • Yuk!

17
Inheritance and Cloneable, Serializable
  • Since clone() and readObject() behave a lot like
    constructors, these methods cannot invoke
    overridable methods either.
  • Problem access to uninitialized state
  • For Serializable
  • readResolve(), writeReplace() must be protected,
    not private (or they will be ignored in subclass.)

18
Bottom Line
  • Be sure you want inheritance, and design for it,
    or
  • Prohibit inheritance
  • Make class final, or
  • Make constructors private (or package-private)

19
Item 18 Prefer Interfaces to Abstract Classes
  • Existing classes can be easily retrofitted to
    implement a new interface
  • Same is not true for abstract classes due to
    single inheritance model in Java
  • Interfaces are ideal for mixins
  • Example Comparable interface
  • Interfaces arent required to form a hierarchy
  • Some things arent hierarchical

20
More Interfaces
  • Wrapper idiom a potent combination with
    interfaces
  • See ISet example
  • Possible to provide skeletal implementations for
    interfaces
  • java.util does this with AbstractCollection,
    AbstractSet, AbstractList, and AbstractMap

21
Example for AbstractList
  • static List intArrayAsList(final int a)
  • if (a null throw new NPE()
  • return new AbstractList()
  • public Object get(int i)
  • return new Integer(ai)
  • public int size() return a.length
  • public Object set(int i, Object o)
  • int oldVal ai
  • ai ((Integer) o).intValue()
  • return new Integer(oldVal)

22
This Implementation Does a Lot!
  • The List interface includes many methods.
  • Only 3 of them are explicitly provided here.
  • This is an anonymous class example
  • Certain methods are overridden
  • Note that it is possible to add a method to an
    abstract class in a new release
  • It is not possible to add a method to an
    interface

23
Item 19 Use Interfaces Only to Define Types
  • Example that fails the test
  • Constant interface avoid
  • public interface PhysicalConstants
  • static final double AVOGADROS
  • Why is this bad?
  • Users of a class that implements this interface
    dont care about these constants!
  • Think about the client, not the implementor

24
Alternative to Constants in Interfaces
  • Constant utility class
  • public class PhysicalConstants
  • public static final double AVOGADROS

25
Item 20 Prefer Class Hierarchies to Tagged
Classes
  • //Tagged Class vastly inferior to a class
    hierarchy
  • class Figure
  • enum Shape RECTANGLE, CIRCLE
  • final Shape shape // Tag field
  • double length double width // for RECTANGLE
  • double radius // for CIRCLE
  • Figure (double length, double width) //
    RECTANGLE
  • Figure (double radius) // CIRCLE
  • double area()
  • switch (shape)
  • case RECTANGLE return lengthwidth
  • case CIRCLE return Math.PI(radius
    radius)
  • default throw new AssertionError()

26
Item 20 Continued A much better solution
  • //Class hierarchy replacement for a tagged class
  • abstract class Figure // Note NOT
    instantiable!
  • abstract double area()
  • class Circle extends Figure
  • final double radius
  • Circle(double rad) radius rad
  • double area()
  • return Math.PI(radiusradius)
  • class Rectangle extends Figure
  • final double length final double width
  • Rectangle (double len double wid) length
    len width wid
  • double area()
  • return lengthwidth
Write a Comment
User Comments (0)
About PowerShow.com