Objects can be declared with an interface type, but can only be initialized with a concrete type. So
private Clip m_clip;
is fine, as it is only a declaration. Before using m_clip
, you need to initialize it, i.e. make it point to a valid object.
m_clip = new Clip();
would produce a compilation error, as Clip
, being an interface, can't be instantiated. However,
class MyClip implements Clip { ... }
...
m_clip = new MyClip();
is OK: MyClip
is a concrete (non-abstract) class implementing the Clip
interface, so it can be instantiated and used whenever a Clip
is needed. After this statement, the static type of m_clip
is Clip
(this is the type which is known to the compiler at compile time, and to the clients of m_clip
too), but its dynamic or runtime type is MyClip
. This is not traced by the compiler, nor is it necessarily known to the clients of m_clip
. This may look strange based on this simple example, but consider that the actual object may be returned from a method, which can be in another class, not written by you, so noone may know what happens inside there. The concrete type used may not even be visible to the outside world.
Once you initialized m_clip
, its clients can use it (e.g. call its methods). But they only see its public interface, i.e. the methods declared in Clip
. This all may sound complicated, but it has a terrific advantage: the actual (runtime) type of m_clip
can be changed anytime, without affecting its clients. E.g. by changing the line above to
m_clip = new SomeOtherClip();
its implementation is changed, but its clients still can use it without changing anything in their code.