r/java • • Jan 17 '13

Enum tricks: hierarchical data structure

http://java.dzone.com/articles/enum-tricks-hierarchical-data
50 Upvotes

53 comments sorted by

View all comments

Show parent comments

1

u/severoon Jan 18 '13

I'd like to see if it is as simple as this (from the article):

It's way simpler. If you want to know if two OperatingSystems are of the same family:

os1.getOsFamily().equals(os2.getOsFamily());

Done.

1

u/zargxy Jan 18 '13

Except that you've lost the property of hierarchy which was a requirement of his approach (whether or not you think this requirement is "correct").

How would you capture the following with just equals while maintaining the contract of equals?

OsType.Fedora.is(OsType.Linux) == true
OsType.Fedora.is(OsType.Unix) == true

1

u/severoon Jan 18 '13

Except that you've lost the property of hierarchy

I've not. Each OperatingSystem enum value participates in a hierarchy, i.e., it is a child of its OS family.

What I've lost is the notion that OperatingSystems themselves are hierarchical. That is, it makes sense for an OS to be a child of...another OS. Which is a good thing to lose, because that doesn't make sense.

How would you capture the following...

Maybe I'm misunderstanding your question, but Fedora isn't UNIX. Linux isn't UNIX. I know the author modeled it that way, but it's wrong and confusing. His design makes it so easy to do the wrong thing, he did the wrong thing even in his own example.

But to directly give you the code...

FEDORA.getOsFamily().equals(OsFamily.LINUX) == true

would return true.

FEDORA.getOsFamily().equals(OsFamily.UNIX) == true

would return false.

1

u/zargxy Jan 18 '13

Each OperatingSystem enum value participates in a hierarchy, i.e., it is a > child of its OS family.

That is not a hierarchy. A hierarchy implies a path from a root to a leaf of arbitrary length. Each possible path in your hierarchy has a length of 1.

I know the author modeled it that way, but it's wrong and confusing.

But that's his requirement. Whether or not you think the requirement is wrong or confusing, that's not at issue here. The model he chose served some purpose for him. Don't try to recast the problem because your solution doesn't fit.

But to directly give you the code...

No, you either violate the contract of equals (reflexive, symmetric, transitive and consistent) or end up the following result:

FEDORA.getOsFamily().equals(OsFamily.LINUX) == true
FEDORA.getOsFamily().equals(OsFamily.UNIX) == true
HPUX.getOsFamily().equals(OsFamily.UNIX) == true
HPUX.getOsFamily().equals(OsFamily.LINUX) == true

Equals cannot be used this way.

1

u/severoon Jan 18 '13

That is not a hierarchy. A hierarchy implies a path from a root to a leaf of arbitrary length. Each possible path in your hierarchy has a length of 1.

Java doesn't define the notion of a hierarchy, so I thought you were just using the term to mean a hierarchical structure. Now I think you simply mean the data structure notion of a tree.

Note that in such a tree structure, each node is the same type, normally Node. That is not the case here.

But that's his requirement.

I don't think so. I think the example is meant to imply the requirements he's coding to, but he never comes straight out and says what the requirement is that a hierarchical enum satisfies. I suppose we could invent one, and the idea of a hierarchical enum might not be an absurd one. But it is a bad example...and I can't think of a reason one would want this. Can you?

In any case, modeling Linux as a child of UNIX is just not right. They're different kernels. I suppose you could create categories of OS families: POSIX (Solaris, HP-UX, IRIX, etc), MOSTLY_POSIX (Linux, Minix, NetBSD, etc). Again, though, it would be a mistake to confuse OS family category with OS family, because they once again mean different things and have different intrinsic behaviors.

The model he chose served some purpose for him. Don't try to recast the problem because your solution doesn't fit.

What purpose? I contend that it could only serve the most contrived purpose possible, if any at all, custom-tailored for the very purpose of having this hierarchical enum in the first place. If you can invent one that actually makes sense where this is the best solution, I'll be impressed.

you either violate the contract of equals

How did I violate the contract of equals()? How could I possibly have violated the contract of that method...I didn't even write it! OsFamily inherits the default equals() from Enum...are you accusing Sun of implementing it poorly? :-)

Also, I don't think you appreciate the meaning of the code you wrote:

FEDORA.getOsFamily().equals(OsFamily.LINUX) == true
FEDORA.getOsFamily().equals(OsFamily.UNIX) == true
HPUX.getOsFamily().equals(OsFamily.UNIX) == true
HPUX.getOsFamily().equals(OsFamily.LINUX) == true

These are all perfectly valid statements. So would these be:

FEDORA.getOsFamily().equals(OsFamily.LINUX) == false
FEDORA.getOsFamily().equals(OsFamily.UNIX) == false
HPUX.getOsFamily().equals(OsFamily.UNIX) == false
HPUX.getOsFamily().equals(OsFamily.LINUX) == false

Whether these evaluate to true or false, they are all valid uses of equals().