Style and practice question: use of interfaces

D

Dimitri Maziuk

Richard C. Cobbe sez:
.... It appears that many
programmers are in the habit of using java.util.Map instead of, say,
java.util.HashMap.

It depends: if this is used in the API, "HashMap" means "unsorted
map that may contain nulls and provides O(1) put()/get()" whereas
"TreeMap" means "sorted map, probably no null keys, O(log n) put()
and get()".
"Map" means "a map with none of the above guarantees".

-- that is, the programmers actually understand what they're doing
use it that way.

It is similar with hand-rolled interfaces: you declare one when
you have multiple not-too-specific implementations.

Dima
 
S

Stefan Ram

It appears that many programmers are in the habit of using
java.util.Map instead of, say, java.util.HashMap.

To be open, a class that needs a map actually should not even
do:

class Example
{ java.util.Map map = new java.util.HashMap(); }

but rather

class Example
{ java.util.Map map;
Example( final java.util.Map map )
{ this.map = map; }}

The first class is still coupled to HashMap, while the second
class can take advantage of any Map-implementation the client
may have to offer, like a "java.util.FastMap" appearing after
the "class Example" was written. Possibly, a default constructor
might be supplied with { this.map = new java.util.HashMap(); }.
 
R

Raymond DeCampo

Stefan said:
To be open, a class that needs a map actually should not even
do:

class Example
{ java.util.Map map = new java.util.HashMap(); }

but rather

class Example
{ java.util.Map map;
Example( final java.util.Map map )
{ this.map = map; }}

The first class is still coupled to HashMap, while the second
class can take advantage of any Map-implementation the client
may have to offer, like a "java.util.FastMap" appearing after
the "class Example" was written. Possibly, a default constructor
might be supplied with { this.map = new java.util.HashMap(); }.

The problem with this is that it breaks encapsulation. The caller has a
reference to your map. So you cannot assume anything about the contents.

Ray
 
S

Stefan Ram

Raymond DeCampo said:
The problem with this is that it breaks encapsulation. The caller has a
reference to your map. So you cannot assume anything about the contents.

I see. This might be avoided as follows:

public Example( final java.lang.Class mapClass )
{ this.map = mapClass.newInstance(); }

Of course, this solution has other drawbacks.
 
T

Thomas Hawtin

Stefan said:
I see. This might be avoided as follows:

public Example( final java.lang.Class mapClass )
{ this.map = mapClass.newInstance(); }

Of course, this solution has other drawbacks.

Or:

public Example(Factory mapFactory) {
this.map = (Map)mapFactory.create();
}

Now you have the problem that your construction clients have been
informed that you are using maps. And how do the clients know which is
the best choice that meets the implementations criteria. (Also it goes
out of scope for generics.)

In almost all case the choice of map implementation is HashMap. No, is
part of the class-level implementation. At a finer level, in most cases,
code's non-performance functionality should be independent of
implementation. There is no point in specifying the implementation more
than once. The interface is another matter (in static-typing religions).

For a different class of my own divising with no associated Java
interface, I'd still only be specifying the implementation once. I'd
just be using the same word for the interface. With a separate Java
interface, the name uniquely implies an implementation just as much.

Tom Hawtin
 
S

Stefan Ram

Thomas Hawtin said:
public Example(Factory mapFactory) {
this.map = (Map)mapFactory.create();
}
Now you have the problem that your construction clients have been
informed that you are using maps.

One might use:

public Example()
{ this.map =( Map )Environment.new( java.util.Map.class, "fast retrieval" ); }

With an appropriate "Environment" class that can recommend
implementations of interfaces possibly regarding argument
flags at run time.
 
I

Ingo R. Homann

Hi Stefan! :)

Stefan said:
One might use:

public Example()
{ this.map =( Map )Environment.new( java.util.Map.class, "fast retrieval" ); }

With an appropriate "Environment" class that can recommend
implementations of interfaces possibly regarding argument
flags at run time.

But then you are going back to a "global variable" ("fast retrieval")
which is not a good idea, i think!

I prefer your idea to pass a map-class that will be instantiated using
newInstance(). (Of course this solutions also needs a parameterless
default construdtor.)

Ciao,
Ingo
 
S

Stefan Ram

Ingo R. Homann said:
But then you are going back to a "global variable" ("fast retrieval")
which is not a good idea, i think!

The "global variable" in this case would be the class name
"Environment". "Environment" would be a "runtime
implementation server" mapping interfaces and preferences to
implementations.

"fast retrieval" was intended to be a flag meaning "The
requested implementation of 'java.util.Map' should be
optimized for fast retrieval of data."

Other flags might be "fast insertation" or "sorted keys".

One might still tell between flags only specifying prefered
behaviour ("fast insert") and flags with mandatory
requirements ("+sorted keys", "+thread safe").
 
I

Ingo R. Homann

Hi Stefan,

Stefan said:
The "global variable" in this case would be the class name
"Environment". "Environment" would be a "runtime
implementation server" mapping interfaces and preferences to
implementations.

"fast retrieval" was intended to be a flag meaning "The
requested implementation of 'java.util.Map' should be
optimized for fast retrieval of data."

Other flags might be "fast insertation" or "sorted keys".

One might still tell between flags only specifying prefered
behaviour ("fast insert") and flags with mandatory
requirements ("+sorted keys", "+thread safe").

Ah, OK.

But I don't think that it is a good idea to 'encode' this (type-)
information in a string (that is not checked during compile time)!

If you want to use a factory, please pass the parameters in a
(type-)safe way!

Ciao,
Ingo
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,573
Members
45,046
Latest member
Gavizuho

Latest Threads

Top