From: Rhino on
On Mar 15, 3:59 pm, Patricia Shanahan <p...(a)acm.org> wrote:
> Rhino wrote:
> > Is it possible to do a full-on assignment of specific values to a HashMap
> > in an interface? If so, how?
>
> Before actually doing this, I recommend reviewing your design to see
> whether this really makes sense. AMapseems a bit too much
> implementation to belong naturally in an interface. However, if you do
> want to do it, you can put a method to generate themapin a static
> member class declaration.
>
> import java.awt.Color;
> import java.util.HashMap;
> import java.util.Map;
>
> public interface ColorMapTest {
>    Map<String, Color> EIGHT_BIT_COLORS = ColorMapInitializer
>        .getMap();
>
>    static class ColorMapInitializer {
>      staticMap<String, Color> getMap() {
>        Map<String, Color> result = new HashMap<String, Color>();
>        result.put("Black", new Color(0, 0, 0));
>        result.put("Obscure Gray", new Color(51, 51, 51));
>        result.put("Dark Gray", new Color(102, 102, 102));
>        result.put("Light Gray", new Color(153, 153, 153));
>        result.put("Pale Gray", new Color(204, 204, 204));
>        result.put("White", new Color(255, 255, 255));
>        return result;
>      }
>    }
>
>
>
> }- Hide quoted text -
>
> - Show quoted text -

Thank you, Patricia!

Several people replying to my question have raised the issue of why I
am initializing a Map in an interface. Unfortunately, I've been having
major issues with my newsreader ever since posting my two questions
yesterday and have been unable to reply to this newsgroup in any way
other than Google Groups, to my great regret. Let me finally answer
that question now and perhaps people can advise me on a better design
if putting the Map in an interface turns out to be a bad idea.

The map I'm trying to create contains all of the 216 8-bit web-safe
colors, the ones that are supposed to render correctly, without
dithering, on virtually every 8-bit or better OS on virtually every
moniI know that the need for web-safe colors is virtually non-existent
these days on newer OSes with better graphic cards but I'm doing this
primarily as an intellectual exercise, not something that absolutely
has to be done.

Therefore, my Map will contain the 216 web-safe colors and provide
sort of a universe of colors. I want to create some additional classes
called ColorSet and ColorPalette. A ColorSet contains a limited number
of coordinating colors that each have a specific function on a web
page (or an Applet that will appear in a web page). For example, one
color in each ColorSet is for text and another is for backgrounds for
that text. (A ColorPalette is just a bunch of ColorSets that are
selectable by a program. The user chooses a desired ColorSet from the
ColorPalette and can be assured that the ColorSet colors will mesh
nicely with one another.)

I want to make sure that a ColorSet contains only Colors from the Map
of web-safe colors.

Since the Map of web-safe Colors is effectively immutable - the 216
colors have been defined and there aren't going to be any additions or
deletions to the list - it seems reasonable to put them in a some kind
of permanent structure, like an Interface. But maybe there are better
options, like the Enum or EnumMap that someone suggeested elsewhere in
the thread. Or in a class.

I'm not particularly wedded to putting the Map in an interface or even
to using a Map at all. I'm really just looking for a good way to
ensure that ColorSets can only contain specific values rather than any
old Color that can be defined in Java. That's the part of the problem
that interests me. I have no formal Java training so I'm just trying
to figure out a good way to ensure that a given group of somethings,
in this case a ColorSet, is always a subset of another set.

Another example of the same issue might be two-letter country codes.
Given that there is a list of recognized two-letter country codes,
'us' for United States, 'ca' for Canada, etc., how could I ensure that
a group of country codes - let's say, a list of North American
countries - only contains legitimate country codes like 'us' and 'ca'
and no non-existent codes, like 'xx'? (Unlike the web-safe colors, the
list of country codes is mutable as new countries, like Slovakia,
emerge and countries like the Soviet Union disappear. But you get the
idea.)

I'd be delighted to get some guidance on the best way to handle this
sort of situation.

--
Rhino


From: Eric Sosman on
On 3/16/2010 2:39 PM, Rhino wrote:
> [...]
> Since the Map of web-safe Colors is effectively immutable - the 216
> colors have been defined and there aren't going to be any additions or
> deletions to the list - it seems reasonable to put them in a some kind
> of permanent structure, like an Interface. But maybe there are better
> options, like the Enum or EnumMap that someone suggeested elsewhere in
> the thread. Or in a class.

An interface feels wrong for this. The primary purpose of
an interface is to be implemented by classes, to ensure that
the implementing classes provide methods with the right names
and signatures. Sometimes an interface defines constants, in
essence conveniences for the implementors and callers, but this
has now mostly been supplanted (and improved on) by Enums. A
few interfaces exist that specify no methods at all and merely
define constants; this is now viewed as Something We Did When
We Were Too Young To Know Any Better.

> I'm not particularly wedded to putting the Map in an interface or even
> to using a Map at all. I'm really just looking for a good way to
> ensure that ColorSets can only contain specific values rather than any
> old Color that can be defined in Java. That's the part of the problem
> that interests me. I have no formal Java training so I'm just trying
> to figure out a good way to ensure that a given group of somethings,
> in this case a ColorSet, is always a subset of another set.

Putting a Map<String,Color> in an interface will not enforce
any such guarantee on the classes that implement it. Making an
`enum SafeColor' would be a first step, and then you could write
interfaces whose methods took SafeColor parameters and returned
SafeColor values (or List<SafeColor>, etc.). If the interface
specifies methods that return plain Colors, though, there's no
way to guarantee that the Colors come from your chosen few.

> Another example of the same issue might be two-letter country codes.
> Given that there is a list of recognized two-letter country codes,
> 'us' for United States, 'ca' for Canada, etc., how could I ensure that
> a group of country codes - let's say, a list of North American
> countries - only contains legitimate country codes like 'us' and 'ca'
> and no non-existent codes, like 'xx'? (Unlike the web-safe colors, the
> list of country codes is mutable as new countries, like Slovakia,
> emerge and countries like the Soviet Union disappear. But you get the
> idea.)

One way would be to have a Country class, with a static
method like `Country getCountryForCode(String countryCode)'.
The caller hands it a (supposed) country code, and it returns
the designated Country or null (or throws up, if you prefer).

I do not see how an interface would be of any help here.

--
Eric Sosman
esosman(a)ieee-dot-org.invalid
From: Rhino on
On Mar 16, 2:12 pm, Eric Sosman <esos...(a)ieee-dot-org.invalid> wrote:
> On 3/16/2010 2:39 PM, Rhino wrote:
>
> > [...]
> > Since theMapof web-safe Colors is effectively immutable - the 216
> > colors have been defined and there aren't going to be any additions or
> > deletions to the list - it seems reasonable to put them in a some kind
> > of permanent structure, like an Interface. But maybe there are better
> > options, like the Enum or EnumMap that someone suggeested elsewhere in
> > the thread. Or in a class.
>
>      An interface feels wrong for this.  The primary purpose of
> an interface is to be implemented by classes, to ensure that
> the implementing classes provide methods with the right names
> and signatures.  Sometimes an interface defines constants, in
> essence conveniences for the implementors and callers, but this
> has now mostly been supplanted (and improved on) by Enums.  A
> few interfaces exist that specify no methods at all and merely
> define constants; this is now viewed as Something We Did When
> We Were Too Young To Know Any Better.
>
I remember being told that an Interface containing only constants was
a good (or at least reasonable) idea on this same newsgroup some years
ago.... Then again, as you say, the Java Community has gradually
evolved better ways of doing things. I have been away from Java for
several years and things have obviously evolved in my absence. I need
to play some catchup now. What is a better way to keep persistent data
if an Interface is not the best way?

I have a variety of interfaces containing only constants for various
programs. For instance, I use them to store the base names of the
resource bundles I use for a given program and for the name of the log
file that the program should be generating. It sounds like I need to
revisit these and change the way I handle this kind of data. I'm just
not sure what approach I should be using nowadays.

> > I'm not particularly wedded to putting theMapin an interface or even
> > to using aMapat all. I'm really just looking for a good way to
> > ensure that ColorSets can only contain specific values rather than any
> > old Color that can be defined in Java. That's the part of the problem
> > that interests me. I have no formal Java training so I'm just trying
> > to figure out a good way to ensure that a given group of somethings,
> > in this case a ColorSet, is always a subset of another set.
>
>      Putting aMap<String,Color> in an interface will not enforce
> any such guarantee on the classes that implement it.  Making an
> `enum SafeColor' would be a first step, and then you could write
> interfaces whose methods took SafeColor parameters and returned
> SafeColor values (or List<SafeColor>, etc.).  If the interface
> specifies methods that return plain Colors, though, there's no
> way to guarantee that the Colors come from your chosen few.
>
Okay, then a Map in an interface is not the optimum design. That's
fine.

I could certainly put the web-safe colors in an Enum. I'm not clear
yet on the rest though.

Let's say that I want to pre-define some ColorSets that would ship
with program. But customers would also be given a program that would
generate additional ColorSets. However, all ColorSets, including the
ones I define and the ones they define, need to choose their colors
from the set of web-safe colors. How should that be done? I'm not
quite picturing what you have in mind yet.


> > Another example of the same issue might be two-letter country codes.
> > Given that there is a list of recognized two-letter country codes,
> > 'us' for United States, 'ca' for Canada, etc., how could I ensure that
> > a group of country codes - let's say, a list of North American
> > countries - only contains legitimate country codes like 'us' and 'ca'
> > and no non-existent codes, like 'xx'? (Unlike the web-safe colors, the
> > list of country codes is mutable as new countries, like Slovakia,
> > emerge and countries like the Soviet Union disappear. But you get the
> > idea.)
>
>      One way would be to have a Country class, with a static
> method like `Country getCountryForCode(String countryCode)'.
> The caller hands it a (supposed) country code, and it returns
> the designated Country or null (or throws up, if you prefer).
>
>      I do not see how an interface would be of any help here.
>
Fair enough. I expect that I am still thinking in obsolete ways. An
enum that lists all valid country codes could easily be used to
validate a country code that someone proposed to type on a form, for
example. Have the form validations check the country code provided on
the form (I'm assuming a simple text box here, rather than a List) to
see if it's in the Enum; if it is, it's a valid code and if it's not,
the country code is invalid. But this time you suggested a class with
a static method, not an Enum. Is that because the list of countries is
mutable whereas the list of web-safe colors is immutable?

--
Rhino
From: Eric Sosman on
On 3/16/2010 4:17 PM, Rhino wrote:
> On Mar 16, 2:12 pm, Eric Sosman<esos...(a)ieee-dot-org.invalid> wrote:
>> On 3/16/2010 2:39 PM, Rhino wrote:
>>> [...]
> I remember being told that an Interface containing only constants was
> a good (or at least reasonable) idea on this same newsgroup some years
> ago.... Then again, as you say, the Java Community has gradually
> evolved better ways of doing things. I have been away from Java for
> several years and things have obviously evolved in my absence. I need
> to play some catchup now.

You must have been away quite a while. Bloch recommended
against constant-only interfaces in the first edition of "Effective
Java," copyright 2001.

> What is a better way to keep persistent data
> if an Interface is not the best way?

"Persistent data" could mean a lot of different things, and
I don't know which you intend.

> I have a variety of interfaces containing only constants for various
> programs. For instance, I use them to store the base names of the
> resource bundles I use for a given program and for the name of the log
> file that the program should be generating. It sounds like I need to
> revisit these and change the way I handle this kind of data. I'm just
> not sure what approach I should be using nowadays.

Usually, such things are located in relation to a class in
a jar file, often the "Main" class of the "program." Without more
specifics, I can't say whether that makes sense for (or to) you.

> I could certainly put the web-safe colors in an Enum. I'm not clear
> yet on the rest though.
>
> Let's say that I want to pre-define some ColorSets that would ship
> with program. But customers would also be given a program that would
> generate additional ColorSets. However, all ColorSets, including the
> ones I define and the ones they define, need to choose their colors
> from the set of web-safe colors. How should that be done? I'm not
> quite picturing what you have in mind yet.

enum SafeColor {
// define instances for all (and only) the safe colors
}

then

public interface ColorSet implements Set<SafeColor> {
...
}

or

public interface ColorSet {
SafeColor getSafeColorByName(String name);
SafeColor getSafeColorByHue(Color hue);
SafeColor getNearestSafeColor(Color hue);
...
}

Since the methods must return SafeColors, you can be sure they
return nothing that isn't in the enum you defined. If there's
some "default" implementation to go with this stuff, make
ColorSet a class (abstract optional) instead of an interface.

>>> Another example of the same issue might be two-letter country codes.
>>> Given that there is a list of recognized two-letter country codes,
>>> 'us' for United States, 'ca' for Canada, etc., how could I ensure that
>>> a group of country codes - let's say, a list of North American
>>> countries - only contains legitimate country codes like 'us' and 'ca'
>>> and no non-existent codes, like 'xx'? [...]
>>
>> One way would be to have a Country class, with a static
>> method like `Country getCountryForCode(String countryCode)'.
>> The caller hands it a (supposed) country code, and it returns
>> the designated Country or null (or throws up, if you prefer).
>>
>> I do not see how an interface would be of any help here.
>>
> Fair enough. I expect that I am still thinking in obsolete ways. An
> enum that lists all valid country codes could easily be used to
> validate a country code that someone proposed to type on a form, for
> example. Have the form validations check the country code provided on
> the form (I'm assuming a simple text box here, rather than a List) to
> see if it's in the Enum; if it is, it's a valid code and if it's not,
> the country code is invalid. But this time you suggested a class with
> a static method, not an Enum. Is that because the list of countries is
> mutable whereas the list of web-safe colors is immutable?

Mostly. You could use a Country enum if you liked, at the
cost of having to recompile and ship a new version of Country
whenever something changed. A Country class that initialized
itself by reading a code/country list from some resource might
be easier to mutate. (The resource might even be a URL somewhere,
saving you the effort of "pushing" new files to the installed base.)

There's more than one way to skin a cat. Which is a good
thing, because cats come in different sizes and ferocities ...

--
Eric Sosman
esosman(a)ieee-dot-org.invalid
From: Lew on
Rhino wrote:
>> I remember being told that an Interface containing only constants was
>> a good (or at least reasonable) idea on this same newsgroup some years

Bad advice.

>> ago.... Then again, as you say, the Java Community has gradually
>> evolved better ways of doing things. I have been away from Java for
>> several years and things have obviously evolved in my absence. I need
>> to play some catchup now.

Eric Sosman wrote:
> You must have been away quite a while. Bloch recommended
> against constant-only interfaces in the first edition of "Effective
> Java," copyright 2001.

<http://java.sun.com/docs/books/effective/>
2nd ed.: "Item 19: Use interfaces only to define types"

He calls it the constant interface pattern, but you'll see it in the
literature as the "Constant Interface Antipattern".

One extremely important insight from this chapter is the focus on types. Java
programming with types rides the synergy of interfaces and generics to build
solid code.

From the world of types, it makes perfect sense that interfaces not hold the
kind of Map you describe. That there's a Map in there makes no difference to
the kind of type you need, an immutable set of particular colors with
associated names over which one can search or correlate by or to names. The
difference is in the behaviors and characteristics of that structure, much as
Eric and others have outlined.

From this thread I see that you can use an enum, a static immutable Map (in a
utility class!), an EnumMap, or whatever.

I showed an immutable Map approach upthread. I use the idiom frequently:

private static final Collection<T> stuff; // immutable
static
{
Collection<T> ffuts = // ... instantiate something appropriate
fillWithStuffToBeImmutable( ffuts );
// type T instances need to be immutable
stuff = Collections.unmodifiableCollection( ffuts );
}

and similarly for finer-grain types like List, or for Maps.

Rhino wrote:
>> What is a better way to keep persistent data
>> if an Interface is not the best way?

In a utility class.

Eric Sosman wrote:
> "Persistent data" could mean a lot of different things, and
> I don't know which you intend.

I guess from context they mean data that hangs around immutably.

Eric Sosman wrote:
> There's more than one way to skin a cat. Which is a good
> thing, because cats come in different sizes and ferocities ...

--
Lew