It's generally good practice to depend on abstract types (interfaces or abstract classes) within a system.
In your example, you could indeed write:
SimpleDoc mydoc = new SimpleDoc()
However the problem is that code that uses mydoc
will depend on the concrete type SimpleDoc
. This isn't necessarily a problem in itself, however, suppose you create a new implementation of Doc
, say ComplexDoc
.
You'd change your declaration to:
ComplexDoc mydoc = new ComplexDoc();
Now all the places methods that you pass mydoc
to would also have to change.
However had you used Doc
in the first place you'd have a single change to make with:
Doc mydoc = ComplexDoc();
This is particularly useful when you are working with the Collections API, where it's common to switch one implementation of another or when using Mocking in test case.