I theoretically understand the point why there is no abstract static in Java, as explained for instance in Why can't static methods be abstract in Java .
But how do I solve such a problem then?
My application uses files of a few types, which I want to assign static properties like a description of that file type (like "data file", the other being "config file", etc.).
Obviously, I would put that into a static String so that the description is accessible without instancing a file (useful for the GUI f.i.).
On the other hand, obviously all file types should have some common methods like getStatus(), which obviously I want to inherit from a common superclass MyFileType.
getDescription() would of course be abstract in the superclass.
Tried using a combination of a superclass and an interface, but similar problem: A static implementation of an abstract method is not allowed.
How would a Java guru solve this?
Is it really such a bad implementation that I want to create?
Many thanks,
Philipp
To restate the problem: you want your per-file-type classes to have statically available information on the type (e.g., name and description).
We can easily get part-way there: create a separate class for your type info, and have a static instance of this (appropriately instantiated) in each per-file-type class.
package myFileAPI;
public class TypeInfo {
public final String name;
public final String description;
public TypeInfo(String name, String description) {
this.name = name;
this.description = description;
}
}
and, say:
package myFileAPI;
public class TextFile {
public static final TypeInfo typeInfo
= new TypeInfo("Text", "Contains text.");
}
Then you can do stuff like:
System.out.println(TextFile.typeInfo.name);
(Of course, you could also use getters in TypeInfo to encapsulate the underlying strings.)
However, as you said, what we really want is to enforce the existence of a particular signature static method in all your per-file-type classes at compile time, but the 'obvious' design path leads to requiring an abstract static method in a common superclass which isn't allowed.
We can enforce this at run-time though, which may be good enough to ensure it is coded correctly. We introduce a File superclass:
package myFileAPI;
public abstract class File {
public static TypeInfo getTypeInfo() {
throw new IllegalStateException(
"Type info hasn't been set up in the subclass");
}
}
If TextFile now extends File, we will get this exception when calling TextFile.getTypeInfo() at runtime, unless TextFile has a same-signature method.
This is quite subtle: code with TextFile.getTypeInfo() in still compiles, even when there is no such method in TextFile. Even though static methods are bound at compile time, the compiler can still look through the class hierarchy to determine the compile-time static call target.
So, we need code like:
package myFileAPI;
public class TextFile extends File {
private static final TypeInfo typeInfo
= new TypeInfo("Text", "Contains text.");
// Shadow the superclass static method
public static TypeInfo getTypeInfo() {
return typeInfo;
}
}
Note that we are still shadowing the superclass method, and so File.getTypeInfo() can still be 'meaninglessly' called.
This sounds like a great time to pull out the Fundamental Theorem of Software Engineering:
Any problem can be solved by adding another layer of indirection.
The problem you have right here is that a file carries around multiple pieces of information - what the type of the file is, a description of the file, the file contents, etc. I'd suggest splitting this into two classes - one class representing a concrete file on disk and its contents, and a second that is an abstract description of some file type. This would allow you to treat the file type class polymorphically. For example:
public interface FileType {
String getExtension();
String getDescription();
/* ... etc. ... */
}
Now, you can make subclasses for each of the file types you use:
public class TextFileType implements FileType {
public String getExtension() {
return ".txt";
}
public String getDescription() {
return "A plain ol' text file.";
}
/* ... */
}
You can then have some large repository of these sorts of objects, which would allow you to query their properties without having an open file of that type. You could also associate a type with each actual file you use by just having it store a FileType reference.
annotations could be fine for your purpose.
#FileProperties(desc="data file")
public class DataFile extends XFile { ... }
FileProperties props = DataFile.class.getAnnotation(FileProperties.class);
String desc = props.desc();
Accessing the info still requires reflection, however it's a little better than using static field/method.
Java compiler does not enforce that all subclasses are annotated as such. You can add your logic to the compiler (using annotation processing) but that's too complicated. It's ok to check it at runtime.
Update:
This is also possible:
#FileInfoClass ( DataFileInfo.class )
#public class DataFile
The question is not clear enough to provide an objective answer. Since I cannot give you a fish, this answer is more on the lines of "Teach you to fish" :)
When faced with design issues like these, where you think "duh..now sure why such a simple thing is so hard" more often than not, you are either designing it just incorrectly, or you are overcomplicating things. If I am empathizing correctly, your design issue seems like a "common requirement" yet the language is not allowing for any elegant solutions.
Trace back your design steps/decisions
question all the "obvious" and "of course" you are basing your design on (you are using quite a few above)
see if things can be simplified (don't take any of the OO concepts to their logical extreme. Make compromises based on ROI)
...and you will most likely arrive at an acceptable answer.
If you still don't, post back the classes and interfaces you think you want (with compile errors since language is not allowing certain things), and maybe we can help you tune your design.
I basically had the exact same problem.
You may want to look at the
solutions suggested to me in my question
I liked Bozho's idea, but according to himself it was a bad idea. :) I suppose better programmers can explain why it is so. Ralph's and Jon Skeet's solution also works.
Sounds like you need to use a singleton. Basically, you call a static method like MyFileTypes.getDataFileInstance() which creates a single instance (or reuses if already created) of an object and when you first create it setup the 'constants' as needed. I'll see if I can find you a good example but your post isn't very clear about how you want to use it.
You could create a FileMetadata class that has all the info you need. When your app starts up, you could create instances of FileMetadata, and keep static pointers to them so you can access them from anywhere in the JVM.
This way you put the abstract stuff in the actual instances; anything the stuff that does not call for abstract semantics can be static...
I don't know how a java guru would solve it, but I'd probably create a resource bundle with all the descriptions in a properties file like this:
com.bigcompany.smallapp.files.DataFile=Data file
com.bigcompany.smallapp.files.ConfigFile=Config file
Handling the bundle can conveniently be placed in the superclass or elsewhere.
Another option is to use reflection to access the static fields in each subclass, but then you need to make sure that all the subclasses have a static field with the same name.
There could be other options too, even refactoring the code so that the subtypes aren't represented by a separate class each, but in general there's no watertight solution.
Instead of putting your static properties actually in static properties, put a reference to MyFileTypeDescription as a static property.
i.e.
class MyFileType {
static MyFileTypeDescription description;
...
<your regular attributes>
}
abstract class MyFileTypeDescription {
String name;
abstract String getDescription();
}
Something along this way, if I understood your problem correctly.
Related
So I am writing a program right now and am conflicted about how I should program it. I have two options:
public class Translator {
private Translator(){}; //prevents instantation
/****
***Stuff
***/
public static String translate(String oldLanguage, String newLanguage, String text){
//METHOD Code
}
}
or
public class Translator {
private String oldLanguage;
private String newLanguage;
public Translator(String oldLanguage, String newLanguage){
this.oldLanguage = oldLanguage;
this.newLanguage = newLanguage;
};
/****
***Stuff
***/
public String translate(String text){
//METHOD Code
}
}
Which should I use and why? This will be the API end of my program.
Also, as programmer which do you find more convenient when dealing with APIs and why?
I would prefer to use the stateless version of translator, but I would prefer a state-full version of translated. The reason is, if you get rid of state then you can often get rid of an entire class of synchronization bugs while moving some of the important information closer to where it is actually used. Imagine, for example, if the two language variables were part of a 1000 line class. Would you want to look up how they are set every time they are used?
The reason I like state for translated is whereas a general translator can exist without knowing what languages it is going to be used for, if you lose what languages are used in a translated, you don't know as well what to do with it anymore (similar to losing your units in a math problem).
For the stateful option, a version I like better is, instead of:
...
private String oldLanguage;
private String newLanguage;
use:
...
private final String oldLanguage;
private final String newLanguage;
... and instead of something like:
myTranslator.setLanguages("spanish", "english")
Translated myTranslated = myTranslator.translate(original)
you can use:
Translator spanishEnglish = new Translator("spanish", "english")
Translated myTranslated = spanishEnglish.translate(original)
That's quite an interesting question, which doesn't have a single best answer. The criteria to choose, out of the top of my head, are mainly:
do you intend to instantiate a translator and reuse it several times with the same old and new languages?
does your translator need to keep some state in memory to be able to translate, without having to reload this state every time a translation is needed?
does your translator have other methods that also use the old and new languages?
is there somewhere in the application where the translator would have to be called without even caring/knowing about what the old and new language are, taking a pre-configured translator as argument?
do you need to be able to mock a translator and inject it in various other components of your code to unit-test them?
If the answers to these questions are yes, then a stateful translator (i.e. your second option) should be used. If the answers are no, then you could go with the first option.
As per the Object Oriented Programming standard, class is a representation of an entity. So you should define something as an attribute of class only if those are the properties of the entity represented by class. Having said that, add oldLanguage and newLanguage to your Translator class only if Translator entity has these attributes.
I would prefer to use the first one
public class Translator {
private Translator(){}; //prevents instantation
/****
***Stuff
***/
public static String translate(String oldLanguage, String newLanguage, String text){
//METHOD Code
}
}
why ?
the answer why should I instantiate an object to translate some thing if I can just do it directly .
Translator.translate(S,S,S);
A method of a class can (should?) be static when it does not access any non-static members or methods of this class.
Now this leads us to the question, when a member (field) of a class should be static or not:
A member (field) of a class must be non-static if it is relevant for defining the state of an instance (= object) of this very class.
So in summary, if something is relevant for the state of an object, then make it instance data, if not (only relevant for the calculation), then pass it as parameter into the method.
In addition to that, it becomes now clear, that it only makes sense to create an instance of a class, if you wish to represent a state. If zero non-static members exist, then you don't need to be able to create an instance of your class.
package com.companyxyz.api.person;
public class Man {
public var1;
public var2;
...
private static void createAuth() {
...
}
// public methods go here
...
}
I want to create a new public method that accesses the private method, createAuth, but in a different file. Is there a way to create this new method without writing it or accessing it via an extended class?
Thank you.
No. You can't access a private method from an other class. Because it's ... private.
A private method is not accessible to any external classes, (this includes subclasses).
A workaround might be to use reflection, however this isn't a generally recommended approach for a number of reasons (brittleness, performance problems, breaking encapsulation, etc).
There is no clean and recommended general way to do this in Java. private is private.
But you did not state why you want to do this and what the specific constraints are. Therefore I throw two options into the mix:
You can decompile the class file for Man, set everything you want to protected or public and recompile (and repackage into a jar file). Perhaps there is no need to decompile, perhaps some bit manipulation on the class file can do the job, too.
You can write a custom ClassLoader with a bytecode manipulation library to modify the bytecode of the class at runtime. Then you can also add additional access paths to the stuff you want. Note however that this is extremely advanced/complicated stuff.
Both ways are nothing you can use / should use for normal applications or the usual framework.
I understand that neither a abstract class nor an interface can contain a method that is both abstract and static because of ambiguity problems, but is there a workaround?
I want to have either an abstract class or an interface that mandates the inclusion of a static method in all of the classes that extend/implement this class/interface. Is there a way to do this in Java? If not, this may be my final straw with Java...
EDIT 1: The context of this problem is that I have a bunch of classes, call them Stick, Ball, and Toy for now, that have a bunch of entries in a database. I want to create a superclass/interface called Fetchable that requires a static method getFetchables() in each of the classes below it. The reason the methods in Stick, Ball, and Toy have to be static is because they will be talking to a database to retrieve all of the entries in the database for each class.
EDIT 2: To those who say you cannot do this in any language, that is not true. You can certainly do this in Ruby where class methods are inherited. This is not a case of someone not getting OO, this is a case of missing functionality in the Java language. You can try to argue that you should never need to inherit static (class) methods, but that is utterly wrong and I will ignore any answers that make such points.
You have a couple of options:
Use reflection to see if the method exists and then call it.
Create an annotation for the static method named something like #GetAllWidgetsMethod.
As others have said, try to not use a static method.
There are lots of answers about 'this does'nt make sense..' but indeed I met a similar problem just yesterday.
I wanted to use inheritance with my unit tests. I have an API and several its implementations. So I need only 1 set of unit tests for all implementations but with different setUp methods which are static.
Workaround: all tests are abstract classes, with some static fields with protected access modifier. In all implementations I added static methods which set these static fields. It works rather nice, and I avoided copy and paste.
I too am dealing with this problem. For those that insist that it "doesn't make sense", I would invite you to think outside of that semantic box for a moment. The program I am working with is inherently about reflection.
Reflection, as you know, can take three orders of magnitude longer than straight-up binary function calling. That is an inevitable problem, and the software needs to port to as many machines as possible, some of which will be 32 bit and slower than my development machine to begin with. Thus, the applicability of a class to the requested operation needs to be checked via a static method, and all of the reflective methods are run at once during module booting.
Everything works, first and foremost. I've built the entire thing. The only catch is that a module can be compiled in a .class without compile time checking to see if the identifying static function exists at all, resulting in an innately useless class. Without the identifier, and its included information, for security's sake the module is not loaded.
I clearly understand the issue with the complete definition of "abstract" and "static", and understand that they don't make sense together. However, the ability to have a class method that is compiler-enforced for inclusion is lacking in Java, and as much as I like the language, I miss it. Thus, this is a human constraint on every programmer that ever works on the software, which I'm sure we can all agree is a pain.
There's a lot of 'this makes no sense' or 'this can't be because' and 'why do you want it?' (or worse: 'you don't have to want it!') in all those answers. However, these answers also indirectly give reasons why it should be possible.
It must be differentiated between the concept and the implementation.
Sure, overriding a static method makes no sense. And it also isn't what the question was about.
It was asked for a way to force implementation of a certain static method (or constant or whatever) in every derived class of an abstract class. Why this is required it the matter of the one who wants to write an appllication with Jave, and no business of anyone else.
This has nothing to do with how the compiler compiles the method and how it is done at runtime.
Why shoudl it be possible? because there are things that are class specific (and not instance specific) and therefore should be static, while they NEED to be impleented in every single subclass (or class that implements an interface).
Let's say there is an abstract class 'Being'. Now there are subclasses like 'animals' and 'plants'.
Now there are only mammals and fishes allowed for animals. This information is specific to the animals class, not to any instance nor doe sit belong to any superclass or subclass. However, this information must be provided by teh class, not an instance, because it is required to properly construct an animal instance. So it MUST be there and it CANNOT be in the instance.
In fact, Java has such a thing- Every object has a class specific field 'class'. It is class-specific, not inherited, no override and it must be there. Well the compiler creates it implicitly, but obviously the compiler CAN do it. So why not allowing this for own fields too.
After all, it is just a matter of definition how the combination 'abstract static' is interpreted when the compiler checks the intheritance chain for abstract functions.
Nobody was ever demanding that there should be an inheritance of the superclass class functions (which could still make some sense, depending on what this function actually does - after all classes inherit static functions of their superclasses, even though you might get a warning that you should access it directly when you call it by the subclass))
But to summarize: the Java language offers no way to do it at compile time while there is no reason (othe rthan plain dogmatic) to not doing so.
The only way is to write a static final function to the abstract class that tries to find the static function/field of the subclass when it is loaded (or loads all existing subclasses and checks them). If properly made, it gives a runtime error on first use. Complex and dirty but better than nothing. At least it prevents bugs where you get the information from the wrong superclass.
It won't work for interfaces, though.
A type system allows you to express some constraints among types, but it's limited. That's why javadocs are littered with constraints in human language, asking people to follow rules that the compiler cannot check.
if you want to extend it beyond what language provides natively, you can write your own static analysis tool. that is not uncommon. for example: findbug. also IDEs do that too, they checking thing beyond what language dictates. you can write a plug in to enforce that a subclass must have a static method of such signature.
in your case, it's not worth it. have javadoc in the superclass urge implementors to include a static method, that's good enough.
I'll provide a convoluted way of expressing your constraint anyway, but DO NO DO IT. people get really carried away of make everything checkable at compile time, at the price of making code unreadable.
interface WidgetEnumerator
{
List getAllWidgets();
}
public class Abs<T extends WidgetEnumerator>
{
static List getAllWidgets(Class<? extends Abs> clazz){ ... }
}
public class Sub extends Abs<SubWidgetEnumerator>
{
}
public class SubWidgetEnumerator implements WidgetEnumerator
{
public List getAllWidgets() { ... }
}
How it works: for any subclass of Abs, it is forced to provide an implementation of WidgetEnumerator. subclass author cannot forget that. Now invocation Abs.getAllWidgets(Sub.class) contains sufficient information to resolve that implementation, i.e. SubWidgetEnumerator. It is done through reflection, but it is type safe, there are no string literals involved.
I think I can give you a better answer after seeing your edits--your best bet is probably a factory pattern. (Not lovely, but better than singleton).
abstract class Widget
public static Widget[] getAllWidgetsOfType(Class widgetType) {
if(widgetType instanceof ...)
}
class Ball extends Widget
class Stick extends Widget
class Toy extends Widget
This is not a very good way to do it, but it's typical. Hibernate is the tool you would normally use to solve this problem, this is exactly what it's designed for.
The big problem is that it requires editing the base class whenever you add a new class of a given type. This can't be gotten around without reflection. If you want to use reflection, then you can implement it this way (Psuedocode, I'm not going to look up the exact syntax for the reflection, but it's not much more complex than this):
public static Widget[] getAllWidgetsOfType(Class widgetType) {
Method staticMethod=widgetType.getStaticMethod("getAllInstances");
return staticMethod.invoke();
}
This would give the solution you were asking for (to be bothered by the need to modify the base class each time you add a child class is a good instinct).
You could also make it an instance method instead of a static. It's not necessary, but you could then prototype the method (abstract) in Widget.
Again, all this is unnecessary and sloppy compared to Hibernate...
Edit: If you passed in a live "Empty" instance of a ball, stick or toy instead of it's "Class" object, you could then just call an inherited method and not use reflection at all. This would also work but you have to expand the definition of a Widget to include an "Empty" instance used as a key.
Static methods are relevant to an entire class of object, not the individual instances. Allowing a static method to be overridden breaks this dictum.
The first thing I would consider is to access your database from a non-static context. This is actually the norm for Java apps.
If you absolutely must use a static method, then have it parameterised with instance specific arguments (of a generic type) to allow the different subclasses to interact with it. Then call that single static method from you polymorphic methods.
No. You can't do that. If you're willing to compromise and make the method non-static or provide an implementation of the static method in your abstract class, you'll be able to code this in Java.
Is there a way to do this in Java?
I don't think there is a way to do this in any language. There's no point to it, since static methods belong to a class and can't be called polymorphically. And enabling polymorphic calls is the only reason for interfaces and abstract classes to exist.
Create a context interface containing your method with a name that matches your problem domain. (Name it "World" if you absolutely have to, but most of the time there's a better name)
Pass around implementation instances of the context object.
Ok, maybe my question was poorly asked, it seems like most of you didn't get what I was trying to do. Nonetheless, I have a solution that is somewhat satisfactory.
In the abstract super class, I am going to have a static method getAllWidgets(Class type). In it I'll check the class you passed it and do the correct fetching based on that. Generally I like to avoid passing around classes and using switches on stuff like this, but I'll make an exception here.
static methods can't be abstract because they aren't virtual. Therefore anywhere that calls them has to have the concrete type with the implementation. If you want to enforce that all implementations of an interface have a certain static method, then that suggests a unit test is required.
abstract class A
{
public static void foo()
{
java.lang.System.out.println("A::foo");
}
public void bar()
{
java.lang.System.out.println("A::bar");
}
}
class B extends A
{
public static void foo()
{
java.lang.System.out.println("B::foo");
}
public void bar()
{
java.lang.System.out.println("B::bar");
}
}
public class Main
{
public static void main(String[] args)
{
B b = new B();
b.foo();
b.bar();
A a = b;
a.foo();
a.bar();
}
}
For what it is worth I know exactly what you are trying to do.
I found this article while searching for the reasons I can't do it either.
In my case I have HUNDREDS of classes that inherit from a central base base and I want simply to get a reference like this:
ValueImSearchingFor visf = StaticClass.someArbitraryValue()
I do NOT want to write/maintain someArbitraryValue() for each and every one of hundreds of the inherited classes -- I just want to write logic once and have it calc a Unique Class-Sepcific value for each and every future written class WITHOUT touching the base class.
Yes I completely get OO - I've been writing Java for about as long as it's been available.
These specific classes are more like "Definitions" as opposed to actual Objects and I don't want to instantiate one every time I just need to see what someArbitraryValue() actually is.
Think of it as a PUBLIC STATIC FINAL that allows you to run a Method ONCE to set it initially. (Kinda like you can do when you define an Enum actually...)
I'd make a WidgetCollection class with an abstract Widget inner class.
You can extend the WidgetCollection.Widget class for each of your types of Widget.
No static methods necessary.
Example (not compiled or tested):
class WidgetCollection<W extends Widget> {
Set<W> widgets = new HashSet<W>();
Set<W> getAll() {
return widgets;
}
abstract class Widget {
Widget() {
widgets.add(this);
}
abstract String getName();
}
public static void main(String[] args) {
WidgetCollection<AWidget> aWidgets = new WidgetCollection<AWidget>();
a.new AWidget();
Set<AWidget> widgets = aWidgets.getAll();
}
}
class AWidget extends Widget {
String getName() {
return "AWidget";
}
}
It doesn't make sense to do what you're asking:
Why can't static methods be abstract in Java
According to Misko Hevery that has a testability blog. Developers should avoid 'holder', 'context', and 'kitchen sink' objects (these take all sorts of other objects and are a grab bag of collaborators). Pass in the specific object you need as a parameter, instead of a holder of that object.
In the example blow, is this code smell? Should I pass only the parameters that are needed or a model/bean with the data that I need.
For example, would you do anything like this: Note. I probably could have passed the data as constructor args. Is this a code smell?
public Parser {
private final SourceCodeBean source;
public Parser(final SourceCodeBean s) {
this.source = s;
}
public void parse() {
// Only access the source field
this.source.getFilename();
...
... assume that the classes uses fields from this.source
...
}
}
public SourceCodeBean {
private String filename;
private String developer;
private String lines;
private String format;
...
...
<ONLY SETTERS AND GETTERS>
...
}
...
Or
public Parser {
public Parser(String filename, String developer, String lines ...) {
...
}
}
And building a test case
public void test() {
SourceCodeBean bean = new SourceCodeBean():
bean.setFilename();
new Parser().parse();
}
Another question: With writing testable code, do you tend to write TOO many classes. Is it wrong to have too many classes or one class with too many methods. The classes are useful and have a single purpose. But, I could see where they could be refactored into one larger class...but that class would have multiple purposes.
You will also notice that Misko Hevery advises to group parameters in classes, whenever the parameter count increases or in cases where this is logically acceptable.
So in your case, you can pass the SourceCodeBean without remorse.
A lot of what you are asking is highly subjective, and it is difficult to make useful suggestions without knowing the full scope of what you are trying to accomplish but here is my 2 cents.
I would go with your latter design. Create one class called SourceCodeParser, have the constructor take in filename, developer, etc, and have it have a parse method. That way the object is responsible for parsing itself.
Typically I prefer to pass in parameters to the constructor if they are not too numerous. Code Complete recommends a max of 7 parameters. If you find the number of constructor parameters to be cumbersome you can always create setters off of the fore-mentioned SourceCodeParser class.
If you want a way to institute different parsing behavior I would recommend using a Parser delegate inside of SourceCodeParser and have that be passed in as either a constructor parameter or a setter.
If you have a class who's sole purpose is to associate together various pieces of information, then I see no reason why that class should not be used directly as a parameter. The reason being that the class was coded to do exactly that, so why would you not let it do its job? So I would definitely prefer the former.
Now, this is assuming that the Parser actually needs the information as it's semantically presented in SourceCodeBean. If all the Parser actually needs is a filename, then it should just take the filename, and I would prefer the second method.
I think the only thing that might worry me here is SourceCodeBean becoming a kind of "kitchen sink" of information. For instance, the filename and format fields make perfect sense here. But do you really need the developer and lines? Could those be instead in some sort of associated metadata-information class?
We are in the process of refactoring some code. There is a feature that we have developed in one project that we would like to now use in other projects. We are extracting the foundation of this feature and making it a full-fledged project which can then be imported by its current project and others. This effort has been relatively straight-forward but we have one headache.
When the framework in question was originally developed, we chose to keep a variety of constant values defined as static fields in a single class. Over time this list of static members grew. The class is used in very many places in our code. In our current refactoring, we will be elevating some of the members of this class to our new framework, but leaving others in place. Our headache is in extracting the foundation members of this class to be used in our new project, and more specifically, how we should address those extracted members in our existing code.
We know that we can have our existing Constants class subclass this new project's Constants class and it would inherit all of the parent's static members. This would allow us to effect the change without touching the code that uses these members to change the class name on the static reference. However, the tight coupling inherent in this choice doesn't feel right.
before:
public class ConstantsA {
public static final String CONSTANT1 = "constant.1";
public static final String CONSTANT2 = "constant.2";
public static final String CONSTANT3 = "constant.3";
}
after:
public class ConstantsA extends ConstantsB {
public static final String CONSTANT1 = "constant.1";
}
public class ConstantsB {
public static final String CONSTANT2 = "constant.2";
public static final String CONSTANT3 = "constant.3";
}
In our existing code branch, all of the above would be accessible in this manner:
ConstantsA.CONSTANT2
I would like to solicit arguments about whether this is 'acceptable' and/or what the best practices are.
A class with only static fields is a code smell. It's not a class.
Some people use interfaces, so they can implement it to use the constants more easily. But an interface should be used only to model a behaviour of a class. (http://pmd.sourceforge.net/rules/design.html#AvoidConstantsInterface) Using static imports from Java 5 removes the need for simple constant usage at all.
Are your constants really Strings, or just used as Strings. If they are different options for some type (so called enumerations), you should used typesafe enumerations, using enum in Java 5 or the Enum provided by Commons Lang. Of course, converting your code to use enums might be a little work.
You should at least split the constants to groups of related constants in files with proper business name. Moving the final members is easy in IDE and will update all usages.
If you can afford it, convert them to enums then. (Think about using about a script to do that, often it's possible.) Class hierarchies are only usefull, if there is a relation between the constants/enums. You can keep the Strings if you have to but still think about them as entities, then extends might make sense for some (describing is-a relation). First enums can be simple classes made by yourself if serializing is not a problem. Enums are always favourable due to their type safe nature and the extra name showing intend or business/domain specific things.
If the constants are really String constants use a Properies or ResourceBundle, which can be configured by plain text files. Again you can script the refactoring using the constant names as resource bundle keys and generate both files automatically.
I don't like it, but it's probably the best you can do right now.
The right answer would be to break up the constants into coherent groups, fixing the code breaks as you go along. In C#, I'd use enums.
Peter Kofler has already discussed how you might wish to better organize constants. I'll share how to automate the transition:
The eclipse "Inline" refactoring can automatically replace constants by their defintion, saving you from having to hunt down and change each usage manually. So you'd simply change the code to:
public class ConstantsA {
public static final String CONSTANT1 = "constant.1";
public static final String CONSTANT2 = ConstantsB.CONSTANTFOO;
public static final String CONSTANT3 = ConstantsB.CONSTANTBAR;
}
public class ConstantsB {
public static final String CONSTANTFOO = "constant.2";
public static final String CONSTANTBAR = "constant.3";
}
... and then have eclipse inline COONSTANT2 and CONSTANT3 (while all affected projects are checked out, if you can't do that, look into refactoring scripts), and you're done.
I've seen this done by putting the static final String on an interface, so that you can 'implement' it and not have to worry about what to do when you need a different base class. It's just as accessible that way.
In general though, enums are pretty good at what you are trying to do, and may get rid of the "I'm not sure" feeling you are experiencing, as that's the intention of enums.
I think what you are doing is fine. Yes, the classes are tightly-coupled, but that is kind of the point -- you want to be able to reference only a single class to see all of your project-wide constants.
You do have to be diligent to ensure that ConstantsB contains only constants that are generalizable amongst all your projects, and ConstantsA contains only project-specific constants. If, later on, you realize that there is a constant in ConstantsB that you seem to be overriding in your subclasses a lot, then that's an indication it should've never been put in ConstantsB in the first place.
I think what you've got is a good first step. The next step is to gradually replace all references to ConstantsA.CONSTANT2 and ConstantsA.CONSTANT3 with ConstantsB.CONSTANT2 and ConstantsB.CONSTANT3 until you can remove the extends.
Most IDEs can be configured to show a warning if you refer to a superclass constant via a subclass, and I'd guess static analysis tools like FindBugs can do it, too.
One idea that might be slightly cleaner:
make all the constants classes interfaces
move all the constants out of ConstantsA and call it something like LegacyConstants
have LegacyConstants extend all the other, modular Constants interfaces
deprecate LegacyConstants
The goal would be not to have any inheritance between the Constants interfaces. LegacyConstants would be the only place there's any inheritance, it wouldn't declare any constants of its own, and when it's no longer used -- when every class that did use it instead refers to the proper Constants interface -- you've finished refactoring.
When you extract your constants, have the old class reference the constant defined in the new class. There's really no need to create an inheritance relationship here.
I could be wrong, but I don't think we need constants at all. It just means that you can't change the value of the constants and you probably should.