File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Java in General and the fly likes Bit of Theory regarding Interfaces Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "Bit of Theory regarding Interfaces" Watch "Bit of Theory regarding Interfaces" New topic
Author

Bit of Theory regarding Interfaces

Nick George
Ranch Hand

Joined: Apr 04, 2004
Posts: 815
Right, we all know the basic function of interfaces, the whole method thing, so we can refer to lots of differnt Classes, but call the same method on them all, at the same place. BUT... lately, I have found significant use for the fact that interfaces can also act as a container for finals. Perhaps an example will illustrate my point. I have a game, with various classes extending combinations of interface Thing, interface Drawable, interface Advanceable. However, to facilate increased communication between various panels, I have each top level class implement GameCodes, which i fancy to be a sort of common language. Game codes is as follows:

Thusly, i can refer to PEON, or, fire an event from my ControlPanel to my Game Panel with the code GO, and everyone knows what i'm talking about.
And now.... The Question
If I may have these finals, why, pray, am i restricted from having static methods? For instance, i'd like to have a getID(Thing thing) method that
returns the code for a thing, (i.e. a Peon would return PEON). Now, this is not undoable, for i can simple make a class within GameCodes called like ID with the static method.
BUT
Why must i do this? my logic says that if finals are allowed, so should static methods. They're kind of comparable, no?
Just curious for the brilliant and illuminative explanation.


I've heard it takes forever to grow a woman from the ground
C. Nimo
Ranch Hand

Joined: Mar 23, 2004
Posts: 82
Hi.
In my opinion - you got it partly right.
It is true that using finals in interfaces could be nice, for example, when you define an interface-package, and want the implementing classes to have your finals. Take a look at javax.jms package for example, in the interface Session - you have finals for the ack modes and stuff. When you write your implementing adapter to javax.jms, your SessionImpl will extend the Session interface, and you will have all those finals in their correct context.
However, you are referring to something that's different. Remember that an interface isn't supposed to be used as a repository of variables, definitions and methods - it is suppose to allow you a way to treat your classes. (Saying - this class here is a mammal, etc.) What you are trying to do is a bit different, and what you probably want to use is a different mechanism - something along the line of a Singleton object - which is a class that has only one instance, with all the finals, statics, and static methods you want. Put this class in your package, or import it to the classes that you need to use it in - and you got it all in a better way.
What you were doing is a bit like copy-pasting your code to each and every one of your implementing classes (a little like c's #include) - Think what happens if you now change the interface - how many classes do you have to recompile?
Also - when you have the interface this way - you are limiting your options for methods/variables names in the implementing classes.
What you could do, if you don't want to use a singleton class as a repository, is use the fully qualified interface instead of implementing it. i.e. instead of accessing PEON inside an implemeting class, use GameCodes.PEON, and do not implement.
Nimo.
Nick George
Ranch Hand

Joined: Apr 04, 2004
Posts: 815
Yeah, I suppose you are right about the singleton class. You see, the heart of the issue lies in the fact that I am, at heart, a lazy man. If i were to make GameCodes a singleton class, I would have to type GameCodes.PEON. Who wants to do that?! And now i have to go back and change it all, because, of course, you are correct. Lazy man does twice the work, eh?
Nick George
Ranch Hand

Joined: Apr 04, 2004
Posts: 815
there is nothing akin to #include, is there?
C. Nimo
Ranch Hand

Joined: Mar 23, 2004
Posts: 82
Well, a few years ago I was using a pre-processor for PLI and ASM/370 to do exactly that (change PEON to GameCodes.PEON and the likes..) how the times change, hey?
My commander in the army used to say whenever we bought a new computer that 'The poors can not afford to buy cheap products' - and that's because they can't afford to but them over and over again.
Have fun.
Nimo.
sever oon
Ranch Hand

Joined: Feb 08, 2004
Posts: 268
I used to wonder this too until I really learned what interfaces are about. They're solely about specifying a contract for implementing classes, and no implementation at all. As soon as you allow an interface to have functionality, then it is no longer a "purely abstract" thing, and that's bad.
For a good discussion of why abstraction is important, read this article over at Object Mentor. They have a sizable collection of articles ranging over a wide array of important topics, and judging from the questions you've been asking around this board, I think you'll find them very interesting.
Basically, the take-away is that interfaces are points of high dependency, meaning that you should write an interface with the idea in mind that nothing about it will change, ideally ever. In every software project, it's useful to separate the code that will change as the product evolves from the code that will not change, because in this way, as the product does evolve, you can form dependencies in the proper fashion. Namely, you can freely depend upon APIs that will not change from several places, secure in the knowledge you won't have to rewrite that code unless that API changes, and that API shouldn't ever change. (See the logic?) The article explains why it's not just APIs, either...even changing code buried underneath those APIs can have a disruptive effect when it comes to deployments. You'll have to read the article for the why's and wherefore's.
Now...on to using interfaces as a collection of constants. DON'T DO IT. I know you've seen it done, I know you've probably even seen Java books and Java experts recommending it as a good practice. It's an anti-pattern, and you shouldn't do it.
When you put something in an interface, you are basically saying that it is part of a contract. Classes that implement that interface agree to abide by that contract. The reason interfaces were invented, and this agreement is valuable, is because it allows those classes to be used polymorphically...if a class implements an interface it's saying, hey, I behave this way, you can trust that I do what the contract in the interface specifies, use me in that way and I'll respond appropriately.
If you collect constants in an interface, and a bunch of classes implement that interface, what contract are they agreeing to abide by that would make it useful to treat them polymorphically? None, that's what. They're not agreeing to any contract specified in the interface. The interface itself doesn't specify a contract, and therefore it would be totally useless for some other class to treat them polymorphically. Picture it:

Would it ever make sense for someone to write code like the following:

What possible use is it to collect these objects which have nothing to do with each other other than the fact that they needed to use one of the constants specified in that interface? You might as well rewrite it to be an Object[] instead, that would be less misleading. There's never a good excuse to treat classes that implement this interface polymorphically.
So, in keeping with proper OO, you shouldn't even put these constants in an interface, because interfaces scream out, "Implement me". Instead, collect them into a final class, and let classes use them from there instead of adding a meaningless interface to their inheritance hierarchy:

This is much better. In fact, this very anti-pattern is why the next Java release, 1.5, has a static import facility. So in the next release of Java, you won't have to say "MathConstants." anymore, and you don't have to implement a constants interface either. You can simply say at the top of your class "import static MathConstants.*".
sev
Nick George
Ranch Hand

Joined: Apr 04, 2004
Posts: 815
Very intriguing. However, you say alot of good uses of interfaces, or, more accurately, THE CORRECT use of interfaces, and i make use of many, many, such interfaces, (interface Advanceable, with nothing but public void advance(double milliseconds), dig?). But, you never really say the harm in useing interfaces as collection of finals. I was in the process of following the Gentleman's advice about the Singleton class, when i realized, I gotta be ME! I'm a lazy man, and i LIKE not having to type GameCodes.PEON. (for the sake of argument, i'm going to ignore this about importing statics for now... i'll get to that in a bit). No, you would never make an array of GameCodes, the very idea is preposterous. But just because you wouldn't use it that way, doesn't mean you can't do it this way. Dig?
I will never change anything in the interface, for the simple reason that there is nothing to change. This italics button is rather fun, eh? The final is the final, and it is final. Agreed I'm not using this interface to call a Human, an Elephant and a Marmot all mammals, but i am getting a useful purpose out of it.

SO...
What is wrong with that?
Now, on to the importing of statics... I am intrigued... here i am like a sucker with 1.4.2... you got me reading about all the fun new features... Generics, man... wave of the future... I never would have found out about that without you... you've done me a great service.
Nick George
Ranch Hand

Joined: Apr 04, 2004
Posts: 815
also, forgive a poor fool's question: what's an anti-pattern?
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Joseph George:
also, forgive a poor fool's question: what's an anti-pattern?

An Anti Pattern is a solution to a common problem that first looks like a good idea, but most often backfires badly when applied.
A documented Anti Pattern also explains why it is a bad idea, and what better solutions exist.
See http://c2.com/cgi/wiki?AntiPatterns


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
sever oon
Ranch Hand

Joined: Feb 08, 2004
Posts: 268
Well...it's not particularly harmful to use interfaces as constants and then implement those interfaces to avoid the extra typing, *if* you follow some self-imposed rules. It will likely never manifest itself as some kind of wrecking ball to your app, just as no single patch, work-around, or hack takes an application down. It's the accumulation of these things that does the trick.
The main thing you're losing with this particular use of interfaces is the segregation of data (in this case constants) into their own little encapsulated namespace. Think of it this way, you create a constants interface and implement it on your class. Then someone comes along and extends your class at some point. Then someone extends that person's class. Then another guy extends that one, and has a need to use some of those constants. So he uses them, and since you've implemented that interface, so, now, does he, so he can save typing too.
Now I come along, and it's my job to maintain that guy's code. I see these funky constants show up in his class that aren't defined anywhere, and until I trace up the hierarchy all the way back to your class, I'll never know where they come from. Once this pattern is used, it gets used a LOT, and EVERY constant is like this. You always have to chase them down rather than having it explicitly spelled out for you. Kind of reminds of those nasty header files in C++ with their multitudes of preprocessor directives. It's only a matter of time until Joe-Bob extends my class and has a name collision with a constant he's using from a different interface.
But this is minor compared to other problems you can run into. For example...let's say that I'm writing a distributed application in which I need tight control over dependencies between packages. Now, it's fine in my application for the package containing your class (package X) to depend on the package containing your constants interface (package Y). And now I want to write a class in some other package (Z, let's say) that extends your class in X. But it's not acceptable for package Z to have a dependency on Y...it should only be dependent on X.
This may seem like a small thing, but it is a HUGE thing as we move into a world of distributed applications that work with each other via web services. Most of the applications I work on these days are deployed as multiple WAR files over multiple servers...most of the time, the web servers are heterogeneous: WebLogic here, Tomcat there, JBoss over in the corner. Managing dependencies can make or break the success of an app, and by polluting the inheritance hierarchy of your class, you've guaranteed that everyone who extends your class is coupled to that constant interface.
If you read up on the Dependency Inversion Principle and the Stable Abstractions Principle at the link I provided in my previous post to Object Mentor, you'll quickly get an idea of why these things matter. One thing I've learned from those articles: extensibility is a fickle thing.
sev
[ April 14, 2004: Message edited by: sever oon ]
Jeroen Wenting
Ranch Hand

Joined: Oct 12, 2000
Posts: 5093
A better alternative to putting a load of constants in an interface is putting them all in a class (might even be possible to make it abstract, I'd have to check) as static final members.
Your syntax will be the same but you're separating the data from the contract which is what interfaces are all about.
You could make that abstract class implement your Peon interface and extend all your Peons from it if you want, but you don't need to.


42
Warren Dew
blacksmith
Ranch Hand

Joined: Mar 04, 2004
Posts: 1332
    
    2
Originally posted by Joseph George:
I'm a lazy man, and i LIKE not having to type GameCodes.PEON.
SO...
What is wrong with that?

As sever oon hints at, when you come back to your code six months from now, you'll see "PEON" all over the place, and you'll have no clue where it comes from or what it means. You'll spend half an hour tracing through the code figuring out it came from the "GameCodes" interface six steps up the inheritance hierarchy, when if you had just spent the extra 30 seconds typing "GameCodes." thirty times, you would have known exactly where to go to figure out what it meant, saving you 29 minutes. Multiply this by the number of constants you're defining, and you'll find that the coffee break you saved from not typing as much turns into an entire weekend that you get to waste later on.
Which begs the question, "why did they allow constants in interfaces in the first place?"
The answer to that is because it's an easy way to specify legal argument values or legal return values required by the contract for various methods in the interface. For example:

That way, you get in the habit of typing things like bfg.shootSplat(SplatShooter.ALBINO), which gives you an easily debugged compiler error. Doing things your way, you get in the habit of typing things like bfg.shootSplat(ALBINO), which loses you a client.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Warren Dew:
You'll spend half an hour tracing through the code figuring out it came from the "GameCodes" interface six steps up the inheritance hierarchy, when if you had just spent the extra 30 seconds typing "GameCodes."

Unless you use a modern IDE, which will tell you in a matter of seconds.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Joseph George:
No, you would never make an array of GameCodes, the very idea is preposterous.

Actually, it isn't that preposterous.
I typically prefer to use the Typesafe Enum pattern instead of int constants. Typically, you bind different behaviour to that constants, most often using switch statements or the like. With a Typesafe Enum, you can put that behaviour into the constant itself by making use of polymorphism (thereby refactoring the Typesafe Enum towards the State/Strategy pattern).
BTW, JDK 1.5 will have inbuild language support for Typesafe Enums, too...
Nick George
Ranch Hand

Joined: Apr 04, 2004
Posts: 815
Now, here's where I stand: Good Programming Practice Joe follows you to a degree, but I fear my doppleganger still has some arguments to make. Thusly, allow me to play Devil's Advocate for a minute, as my doppleganger, Joe, the Programming Jerk.
I'm Joe, the Programming Jerk. I'm the only one working on this project. I don't make anything private, I'd only be restricting myself. I don't comment my code, because I know what it all does, and if you can't figure it out, maybe you should go read HelloWorld. And as for interfaces, I can tell Joshua Bloch where he can stick his contracts, I'll use them anyway they work. I use the Eclipse editor, it will tell me where PEON came from.
Alright, the straw man is set up, feel free to beat him down about the interfaces.
Finally, can the Gentleman direct me somewhere I may learn about Typesafe Enums? I've heard that word thrown around enough, time to find out just what it means.
sever oon
Ranch Hand

Joined: Feb 08, 2004
Posts: 268
If you're that worried about having to type the name of the final class which contains your constants, do this instead. Type in a short bit of craziness at the beginning of each constant instead:

Then, right before you compile, do a global search and replace on $A and stick in GameCodes. Ta da.
I also disagree with someone who earlier said constants are allowed in interfaces because they allow you to specify contracts. It's just as easy to stick those constants in a separate final class and refer to them from the interface, and that's a more appropriate place for them even in that case...that is, if you expect anyone to extend your interface. That way, implementing classes will not fall victim to the same kind of lazy notation we're trying to avoid.
sev
Tarun Ramakrishna Elankath
Greenhorn

Joined: Mar 27, 2002
Posts: 27
Originally posted by Jeroen Wenting:
A better alternative to putting a load of constants in an interface is putting them all in a class (might even be possible to make it abstract, I'd have to check) as static final members.

Check out the new 'enum' construct in JDK1.5 for type-safe constants - these are constructs that are *specially* meant for being containers of constants.
For JDK's < 1.5, the Type-safe enum pattern (Of Joshua Bloch's 'Effective Java' fame) provides the best solution in terms of OO and safety.
C. Nimo
Ranch Hand

Joined: Mar 23, 2004
Posts: 82
Hi.

I'm Joe, the Programming Jerk. I'm the only one working on this project. I don't make anything private, I'd only be restricting myself. I don't comment my code, because I know what it all does, and if you can't figure it out, maybe you should go read HelloWorld. And as for interfaces, I can tell Joshua Bloch where he can stick his contracts, I'll use them anyway they work. I use the Eclipse editor, it will tell me where PEON came from.

I see four options here, regarding Joe's future.
1. He'll forever be a Programming Jerk, that is - as long as he's able to switch jobs every six months or so, when the team-leader discovers that he knows < 0 about Object Oriented programming, and fires him.
2. He'll become a better programmer and spend an hour every day cursing the ancestors of the programming jerks who wrote their code like he used to when he was little.
3. He'll get a job doing something else. I can testify that PL/I is a great language to code in.
4. He'll have to program in ADA some day, and discover he can't make this kind of errors any more...
Nimo.
Greg Reinl
Ranch Hand

Joined: Feb 11, 2003
Posts: 45
direct me somewhere I may learn about Typesafe Enums?

Joshua Bloch's Effective Java, Chapter 5, item 21.
Barry Andrews
Ranch Hand

Joined: Sep 05, 2000
Posts: 523

I hate to burst the bubble of the Java bigots in this forum, but what Joseph is doing is perfectly fine. By definition an interface is "a device or a system that unrelated entities use to interact." The docs from Sun state the following:
"Interfaces are useful for the following:
* Capturing similarities among unrelated classes without artificially forcing a class relationship.
* Declaring methods that one or more classes are expected to implement.
* Revealing an object's programming interface without revealing its class. "
Defining constants in an interface fully complies with item number one. You have constants that are used throughout the program, why not put them in an interface? This is where people take OO too far. If an interface has nothing but constants in it, it should be pretty obvious that it's not an interface that needs to be implemented. It's more of a namespace than anything. This is perfectly valid, and why there are many articles and books that recommend this approach.
However, my preference is to not implement this kind of interface in any of my classes. Just import it, and use the constants. Because really you are not implementing anything. The only advantage to implementing is you don't have to give a qualifier. But my preference is to have the qualifier.
Keep your interface, Joseph!
Warren Dew
blacksmith
Ranch Hand

Joined: Mar 04, 2004
Posts: 1332
    
    2
Unless you use a modern IDE, which will tell you in a matter of seconds.

Actually, I use an IDE with that feature, and I still don't use the feature. It doesn't take that long for matters of seconds to add up to half an hour or an entire weekend when you have tons of constants like "PEON" and "LEUCOUS" hanging around.
I also disagree with someone who earlier said constants are allowed in interfaces because they allow you to specify contracts. It's just as easy to stick those constants in a separate final class and refer to them from the interface, and that's a more appropriate place for them even in that case...that is, if you expect anyone to extend your interface.

That was me. I agree with you about best practice - and with others about using typesafe enumerations rather than constants. However, it's still the case that constants are allowed in interfaces in Java. What's your theory about why Sun allowed them?
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Warren Dew:
Actually, I use an IDE with that feature, and I still don't use the feature. It doesn't take that long for matters of seconds to add up to half an hour or an entire weekend when you have tons of constants like "PEON" and "LEUCOUS" hanging around.

Which begs another question for me: How often *do* you want to know where a constant comes from, and why?
Just curious...
Warren Dew
blacksmith
Ranch Hand

Joined: Mar 04, 2004
Posts: 1332
    
    2

I'm Joe, the Programming Jerk. I'm the only one working on this project. I don't make anything private, I'd only be restricting myself. I don't comment my code, because I know what it all does, and if you can't figure it out, maybe you should go read HelloWorld. And as for interfaces, I can tell Joshua Bloch where he can stick his contracts, I'll use them anyway they work. I use the Eclipse editor, it will tell me where PEON came from.

I see four options here, regarding Joe's future.
1. He'll forever be a Programming Jerk, that is - as long as he's able to switch jobs every six months or so, when the team-leader discovers that he knows < 0 about Object Oriented programming, and fires him.

Unless he's hired by a nontechnical manager, who might end up thinking he's the best programmer because he seems to be more productive (since he can read others' code but they can't read his quasiintentionally obfuscated code). Then he'll be the one that stays around while others get fired or get fed up and leave.
[ April 15, 2004: Message edited by: Warren Dew ]
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Greg Reinl:

Joshua Bloch's Effective Java, Chapter 5, item 21.

And http://www.google.de/search?q=typesafe+enums
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Joseph George:
I don't make anything private, I'd only be restricting myself.

Hell, "private" isn't much more than a comment, anyway - at least as long as you can change the code.

I don't comment my code, because I know what it all does, and if you can't figure it out, maybe you should go read HelloWorld.

Well, I typically don't comment my code, either, because I know how to write code so that it doesn't need comments. But if you can't figure it out, I possibly need to learn how to make it even more expressive...
And as for interfaces, I can tell Joshua Bloch where he can stick his contracts, I'll use them anyway they work. I use the Eclipse editor, it will tell me where PEON came from.

I sometimes use iterfaces for declaring constants, too. I wouldn't use this idiom for published APi, though.
Until now, I haven't been bitten by this practices.
Anyone with *personal* bad experience - instead of "just" academic "pureness" arguments?
Warren Dew
blacksmith
Ranch Hand

Joined: Mar 04, 2004
Posts: 1332
    
    2
Originally posted by Ilja Preuss:
Which begs another question for me: How often *do* you want to know where a constant comes from, and why?
Just curious...

For me, every time I read one.
I mean, suppose you see "PEON" in a piece of code. What does it mean? To me, "peon" might be appropriate as a class name, or as a variable name (in a function that deals with one peon at a time), but as a constant? Is there only one peon in the game, so that it can be a constant rather than a class? Or is it, most likely, an arbitrary constant for use with some class, function, or interface?
If the latter, then I can't know what's going on just by reading the code. Only if it's preceded by a class, interface, or other namespace name am I going to have a clue what it's really there for.
If the "PEON" example doesn't work for you, consider the constant "MAX_VALUE". Is it 3.4E38, or is it 9223372036854775807, or is it 2147483647? If I type "PI", will I get Math.PI, which is a double, or will I get some other PI, which may have a different accuracy? Fortunately, Java's built in constants are set up in a way to discourage this, but if they were defined in interfaces rather than classes, and people implemented those interfaces to 'save typing', that's what would happen.
Perhaps he thinks he's going to somehow make sure that there's only one "PEON" constant ever defined? In my experience, such global constant definitions do not work. In my experience, another programmer will want to reuse a constant name sooner or later. In fact, in my experience, I'll end up forgetting about that constant and end up wanting to reuse it myself after a few months.
To clarify, I don't have an objection to defining constants in interfaces, I only object to "implementing" those interfaces to save typing on the constants. Typically code is read multiple times for each time it's written, so it makes sense to do the extra typing to save on comprehension time when it's read.
Not to mention that, from an OO standpoint, what does it mean for, say, a Spaceship class to implement a bag of constants contained in an interface named, say, FloatConstants? I doubt that the class satisfies an "is a" relationship. To put it another way, I don't think Spaceship.MAX_VALUE has a very intuitive meaning in this case.
And yes, I've been bitten by things like that. Many times.
sever oon
Ranch Hand

Joined: Feb 08, 2004
Posts: 268
Mr. Barry Andrews...I could not let your comment pass about Sun being ok with specifying interfaces full of constants. I tried, but it didn't take.
It's true that at first they advocated this possibility for interfaces, but they quickly realized it was not robust coding when Java got picked up and started getting used as a so-called Real Programming Language.
As proof of Sun's not-so-newfound disdain for this practice, consider the static import facility they are providing as part of the Tiger release, JDK 1.5. There is simply no other purpose for this particular feature except to discourage the use of interfaces as constant bags and to encourage the use of public final classes.
Your move, sir. B)
sev
Barry Andrews
Ranch Hand

Joined: Sep 05, 2000
Posts: 523

Yes, but the JSR only talks about discouraging "implementing" such an interface, which I do agree with. As I said before it doesn't make sense to "implement" such an interface because you're not implementing anything.
Point taken about Sun discouraging an interface full of constants, but I still believe it is a matter of opinion/preference. You can't say for years in articles and books that putting constants in an interface is good practice and then all of a sudden say it's wrong and expect everyone to jump on the bandwagon. Use a final class, use an interface. So what? As long as everyone else knows what you are doing. Maybe I will use a final class in my next project!
Nick George
Ranch Hand

Joined: Apr 04, 2004
Posts: 815
It seems to me that the arguements made against implementing a constant interface sort themselves into mainly a few veins, which i will attempt to list here, that i may later adress them.
1. PROPOSED: that implementing such interfaces will cause confusion as to the place of origin of such finals.
2. PROPOSED: that eventually, someone will try to use the same final name as one stated in the said interface, leading to additional confusion.
3. PROPOSED: that, specifying no contract, such use betrays the intention of interfaces as defined by their creators.
Before I proceed, let any man with complaint unique enough from those already enumerated add his own to this list, that it may be as complete as is possible.
Tony Morris
Ranch Hand

Joined: Sep 24, 2003
Posts: 1608
This is a flawed approach.
You want the Typesafe Enum Pattern.
http://java.sun.com/developer/Books/effectivejava/Chapter5.pdf Item 21
Also, J2SE 1.5 sees the introcution of the enum keyword.


Tony Morris
Java Q&A (FAQ, Trivia)
Nick George
Ranch Hand

Joined: Apr 04, 2004
Posts: 815
well, i had planned to say why none of those arguments were really all that compellings, but, then i went ahead and read about Type-safe enums. Coolest bit of programming i've ever seen. I rescind any ill comments towards Joshua Bloch, tip my hat, and end my thread.
It was a good one, though, eh?
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Tony Morris:
This is a flawed approach.
You want the Typesafe Enum Pattern.

I love the Typesafe Enum Pattern, but it's no silver bullet.
For example, if I have a FooToXmlWriter and a FooFromXmlReader, it's likely that I need to use the same tag names in their implementations. Defining them as Typesafe Enums would be strange. Defining them as constants in an interface that gets implemented by both the Writer and the Reader is quite convenient. It's certainly somewhat of a hack, and I will certainly switch to using static imports, but as long as I can't do that... <shrug>
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Warren Dew:
For me, every time I read one.
I mean, suppose you see "PEON" in a piece of code. What does it mean?

I am not sure, but I am also currently not working on that code. I'd hope that after some time working on it, I'd have an idea...

To me, "peon" might be appropriate as a class name, or as a variable name (in a function that deals with one peon at a time), but as a constant?

For all the Java projects I've ever worked on, "peon" is an adequate variable name, "Peon" a class name, "PEON" a constant name. Perhaps you should work on your naming convention.
Is there only one peon in the game, so that it can be a constant rather than a class? Or is it, most likely, an arbitrary constant for use with some class, function, or interface?

Wouldn't that most often be quite obvious from the context it is used in? And if not, how would knowing where it is defined help better than giving it a more speaking name?
If the latter, then I can't know what's going on just by reading the code. Only if it's preceded by a class, interface, or other namespace name am I going to have a clue what it's really there for.

Actually, both variables, constants and class names can be preceded by a class name. And if peon could be a class name, how do you know wether the "foo.bar" in foo.bar.peon refers to a package or a class?
If the "PEON" example doesn't work for you, consider the constant "MAX_VALUE". Is it 3.4E38, or is it 9223372036854775807, or is it 2147483647? If I type "PI", will I get Math.PI, which is a double, or will I get some other PI, which may have a different accuracy? Fortunately, Java's built in constants are set up in a way to discourage this, but if they were defined in interfaces rather than classes, and people implemented those interfaces to 'save typing', that's what would happen.

That's a matter of appropriate naming, not of implementing constants from an interface. Constants.MAX_VALUE is much less helpfull than MAX_INT_VALUE.
Not to mention that, from an OO standpoint, what does it mean for, say, a Spaceship class to implement a bag of constants contained in an interface named, say, FloatConstants? I doubt that the class satisfies an "is a" relationship.

"is a" is just a rough heuristic. What is more important is the Liskov Substitution Principle, which isn't violated by this use.
There *is* a drawback - the interface of a class gets bloated by implementing an interface for importing constants. I find that there are cases where it is worth this cost, in pre-JDK1.5.
Nick George
Ranch Hand

Joined: Apr 04, 2004
Posts: 815
ah, thank you... you have come to my aide when all others shunned me... Type-safe enums do look pretty clever, but there are some very real benefits to the ostrosized practice of implementing constants. However, it seems to me that all this will be a moot issue with the release of 1.5. When is that scheduled for, anyway?
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Joseph George:
However, it seems to me that all this will be a moot issue with the release of 1.5. When is that scheduled for, anyway?

Somewhere Q3-Q4 2004, as far as I know. I don't think there is a definitive date yet...
Roger Chung-Wee
Ranch Hand

Joined: Sep 29, 2002
Posts: 1683
Why would you wish to pollute your implementation class's namespace and tell the world that you need these constants? Your data should be kept private!
I'd recommend one of two approaches. If you can safely remove the interface that has only constants, then do so and replace it with a class that declares the constants as static final fields.
The other way, if you are somehow need to use the interface, is to declare a private nested class which implements the interface. This way, you hide the fact that you are using the interface. Later, if your class changes and you no longer need the constants, you can remove the private class. If you failed to do this and you had had your top level class implementing the interface, you are stuck with still having to implement the unwanted interface for fear of breaking something else.


SCJP 1.4, SCWCD 1.3, SCBCD 1.3
Warren Dew
blacksmith
Ranch Hand

Joined: Mar 04, 2004
Posts: 1332
    
    2
Originally posted by Ilja Preuss:
For example, if I have a FooToXmlWriter and a FooFromXmlReader, it's likely that I need to use the same tag names in their implementations. Defining them as Typesafe Enums would be strange.

Have you tried it, and had it work, and still found it to be strange? I've used typesafe enums for similar things, and because of the ability to add more methods, found it to be exactly the right solution. It ceased being strange once I used it and got used to it.
On the other issue, in order to try to be clearer to anyone out there who doesn't play Warcraft and hasn't written a video game, I'll focus on the MAX_VALUE analogy rather than on PEONs.
That's a matter of appropriate naming, not of implementing constants from an interface. Constants. MAX_VALUE is much less helpfull than MAX_INT_VALUE.

At least we're agreed that using an unqualified "MAX_VALUE" isn't good, then.
If you use longer constant names for clarity, which I agree would be better, you would in this case end up with a Constants interface with constants like MAX_INT_VALUE, and MAX_FLOAT_VALUE. I agree that with that setup, the constants would be adequately described even omitting the interface name. On the other hand, once you are using these longer names, I contend that you're no longer saving typing time, which was the original poster's reason for implementing such interfaces.
However, I contend that the way Java actually did it is even cleaner, by grouping related constants into relevant classes. Yes, that means that to be clear, you have to type the qualifier, but I contend that for most people, "Integer.MAX_VALUE" is actually faster to type than MAX_INT_VALUE. I believe it's also faster to read and understand because it uses more mixed case and less 'all caps'.
And I contend that having my class inherit from java.lang.Integer just so I can type 'MAX_VALUE' instead of 'Integer.MAX_VALUE' and save keystrokes - which is cognate to what the original poster is suggesting - is an atrocity, even if I don't violate the Liskov Substitution Principle.
Nick George
Ranch Hand

Joined: Apr 04, 2004
Posts: 815
And I contend that having my class inherit from java.lang.Integer just so I can type 'MAX_VALUE' instead of 'Integer.MAX_VALUE' and save keystrokes - which is cognate to what the original poster is suggesting - is an atrocity, even if I don't violate the Liskov Substitution Principle.

An atrocity, eh?
sort of like what c++ programmers call java, because java does endless extraneous work that used to be done by the programmer?
I contend that it is rather outside of the spirit of programming to call something an atrocity because "that's not the way it's done." The final names i use are following very tight conventions, with just the name being an int code, and thus, i really don't forsee any difficulties in identifying the code later on. Likewise, it shouldn't be too hard for a reader to identify the source.
Warren Dew
blacksmith
Ranch Hand

Joined: Mar 04, 2004
Posts: 1332
    
    2
Originally posted by Joseph George:
An atrocity, eh?
sort of like what c++ programmers call java, because java does endless extraneous work that used to be done by the programmer?

Nah. C++ programmers call Java a "baby language". "Real programmers" multiply pointers, free their own memory, and save keystrokes by writing complex and completely opaque templates.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Roger Chung-Wee:
Why would you wish to pollute your implementation class's namespace and tell the world that you need these constants? Your data should be kept private!

I don't wish to do that. But sometimes it seems to be a cost worth paying.
If you failed to do this and you had had your top level class implementing the interface, you are stuck with still having to implement the unwanted interface for fear of breaking something else.

I only use that pattern when all the clients are under my control, so I wouldn't have to fear breaking something. As I said, I wouldn't use this for published API.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Bit of Theory regarding Interfaces