How to remove common code in similar Java String based Enums - java

I have a class that may have several enums within it.
Each enum is supposed to have a string value associated with each entry.
In order to achieve this, I have added a parametrized constructor,a supporting string class member and overridern the toString method.
However one can see that 50% of the code between my two enums are same. It's just the code to support mapping strings to the Enum values.
How can I move this code to a common place and avoid code duplication?
Edit: Use case is to easily obtain "New York" when I write America.STATES.NY.
Here's what I tried,
1) I tried using a common interface, but the constructors are different.
2) I tried using inheritance, but enums cannot be inherited
public class America {
public enum STATES {
NY("New York"), CA("California");
String displayName;
STATES(String displayName) {
this.displayName = displayName;
}
#Override
public String toString() {
return this.displayName;
}
}
public enum PROVINCES {
ON("Ontario"), QU("Qubec");
String displayName;
PROVINCES(String displayName) {
this.displayName = displayName;
}
#Override
public String toString() {
return this.displayName;
}
}
}

A typical phrase I like to use is "data isn't a part of behavior, and doesn't belong in the code". To be clear (and from my experience), it's much easier to adopt or translate a system that relies on the data for it being loaded from something rather than representing the data in hard-coded values.
public class Region {
private final String name;
public Region(String name) { this.name = name; }
public String getDisplayName() { return this.name; }
public String toString() { return getDisplayName(); }
}
public class Country {
//keeps a map/list of "regions", whether states or provinces or some other type
public Region getRegion(Object key); //lookup a region based on some key, I'll use strings here
}
Country america = /* a country supplied from somewhere */;
String name = america.getRegion("NY").getDisplayName(); //"New York"
This type of approach, while sub-optimal for hard-coded references in your code (like getRegion("NY")), is much more forgiving when you need to modify the data later or make a reference which is loaded from elsewheres (e.g. a user-supplied Region or lookup name). If you use a database, you can keep your code up-to-date without ever having to change the project, just the database itself. And in the end, since all of this data-related information is stored elsewheres, the overall amount of code to handle is vastly reduced.
You can also later add in something to support determining whether a given administrative region is a state or province or something else (which I think an enum is great for):
public enum RegionType {
STATE, PROVINCE, ADMIN_REGION, OTHER,
;
}

You can implement an EnumUtils class and add a static instance of it to every enum class. I implemented an example here: https://stackoverflow.com/a/48199147/7949301.

Related

Determine which fields of a POJO are being accessed in a code

I have a huge (parent) POJO which is being used in some component. The POJO has individual fields as well as nested POJOs as well. Is it possible to determine what all fields/ nested fields from this POJO are being accessed in that component?
I was thinking about JUnits/ aspects but not sure if either would work. I've tried looking through SF/ and Google but could not find any relevant thread for this thing.
Say following is a sample POJO:
public class Student {
private String name;
private Date date;
private Subject subject;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public Subject getSubject() {
return subject;
}
public void setSubject(Subject subject) {
this.subject = subject;
}
}
It has three fields name, date and subject, not all of which would be in use in my component. So I need to determine which are actually being used.
Edit:
Thanks Sharon for pointing out that the getter/setters were protected. I had just generated the class on the fly for the purpose of question and didn't notice the issue. Corrected now.
How the class is initialised: For the purpose of the component, objects will be created from Json/XML data and would have only getters being called.
As for static vs runtime analysis, I'd prefer to achieve it through static code analysis if that's possible otherwise runtime also is fine with me if that's easier.
As for using Decorator pattern, do we have anything without requiring existing code change? That's why I was thinking if JUnits could do this.
First of all, it is odd to see getter/setter methods that are protected. seems to me they need to be public?
Anyway, I would utilize the Decorator design pattern.
From the linked article:
The decorator design pattern allows us to dynamically add
functionality and behavior to an object without affecting the behavior
of other existing objects in the same class.
So, our decorated Student should inherit from the target class. All methods can log their usage and call super to invoke target operation. You didn't say how Student
is initialized, but anyway, you will want to modify that to create instances of LogUsageStudent
public class LogUsageStudent extends Student {
protected String getName() {
// log usage of getName()
return super.getName();
}
// etc
}

Eclipse generate getter/setter for domain objects and classmembers with 'm' suffix

I have a small question regarding generated getter and setter methods in my domain objects.
I want to use a common style guide for my source code. One part of that style guide says that I start each class member name with the prefix 'm' for member.
class User{
String mName;
List<Call> mAllCall;
List<Geo> mAllGeo;
Unfortunately I have a couple of classes with many more member variables. The problem I have is that I am a very lazy developer, and that I create the getter and setter methods in Eclipse with
"Source"->"Generate Getters and Setters".
The result is
public String getmName() {
return mName;
}
public void setmName(String mName) {
this.mName = mName;
}
public List<Call> getmAllCall() {
return mAllCall;
}
public void setmAllCall(List<Call> mAllCall) {
this.mAllCall = mAllCall;
}
public List<Geo> getAllGeo() {
return mAllGeo;
}
public void setmAllGeo(List<Geo> mAllGeo) {
this.mAllGeo = mAllGeo;
}
That is not the result I want. I need this:
public String getName() {
return mName;
}
public void setName(String pName) {
this.mName = pName;
}
public List<Call> getAllCall() {
return mAllCall;
}
public void setAllCall(List<Call> pAllCall) {
this.mAllCall = pAllCall;
}
public List<Geo> getAllGeo() {
return mAllGeo;
}
public void setmAllGeo(List<Geo> pAllGeo) {
this.mAllGeo = mAllGeo;
}
I currently remove and replace the prefix in the method names by hand. Is there an easier way to do this?
For the prefix m, you add the letter m to your list of prefixes in the Java Code Style.
Follow these steps:
open Preferences,
in left panel, expand Java,
expand Code Style,
right panel is where you should now be looking at
You will see a list with Fields, Static Fields, etc. This is what you need to modify.
Set m against Fields.
Set p against the Parameter.
As the name of the field will now be different from the name of the argument, the this. qualification will no longer be added automatically. However, you can check the option Qualify all generated field accesses with 'this.' to have it again.
I suppose that you know the difference between Enable project specific settings and Configure Workspace Settings... in the upper left and right of the window?
I don't like the idea at all, but..
You can write the members without the prefix m, let Eclipse create the getters and setters, an afterwards rename the members (Shift-Alt-R); Eclipse will change the references, but not (unless you explicitly tell it) the getters/setters signature.
The names of the getter and setter methods are derived from the field name. If you use a prefix or suffix for fields (e.g. fValue, _value, val_m), you can specify the suffixes and prefixes in the Code Style preference page (Windows > Preferences > Java > Code Style).
reference at here

Inherited enum redefinition

It is more complex than it sounds, but I think I am obliged to try something like it. I want to make an abstract parent class with a prototyping of an enum (I want to declare the enum with only one value probably that will be the default unitialized one and also declaring a couple of methods that I will be using from the subclass), then I want to class that will extend the abstract parent to actually intialize the very same enum (I know that this practically hides the parent enum) so that the kid class will define a set of items inside the enum, but keep the methods probably.
I do not know much about this level of abstraction so I will now describe the nature of my problem, in case there is a more practical solution:
I have a bunch of files that contain classes that implement a lot of commands based on enums. (e.g. class1 implements Observer has an update method that uses an enum-based switch to decide what command was picked, same applies for the other classes) I now want to abstract this whole thing in a way that I have an enum variable with the exact same name in all classes (e.g. CommandSet) so that I can have a generic method inside the parent that will be able to print a help list to my system using the inside methods of the enum. Now I know I can rewrite the exact same method in every class, but I want to abstract it so that others can keep on extending the library I am making!
Hopefully I am not too confusing or too confused and somone can help me! :)
Edit: Here is an idea of the code (Probably not right):
public abstract class Commands{
enum CommandSet{
// empty command, placeholder
null_command ("command name", "command description");
// the Strings used for name and description
private final String name;
private final String description;
// constructor
CommandSet(String name, String description){
this.name=name;
this.description=description;
}
// get parameters
public String getName(){
return name;
}
public String getDescription(){
return description;
}
}
public void showHelp(){
for (CommandSet i : CommandSet.values()) {
printf(i.getName(),":",i.getDescription());
}
}
}
public class StandardCommads extends Commands implements Observer{
// I want to change the enum here, just changing the values so that null_command ("command name", "command description") will get removed and I will add a dozen other values, but keep the methods that the parent had
// update inherited from Observer
#Override
public void update(Observable observable, Object object) {
// I want the commands inside the switch cases defined inside this class's enum
switch(CommandSet.valueOf(String.valueOf(object)){
case command1: doStuff1();break;
case command2: doStuff2();break;
...
case commandN: doStuffN();break;
}
// other methods
void doStuff1(){
...
}
...
void doStuffN(){
...
}
}
public class NonStandardCommads extends Commands implements Observer{
// Another set of commands here for the enum keeping the same methods it had in the parent
// update inherited from Observer
#Override
public void update(Observable observable, Object object) {
// Other set of commands inside this class used in the switch statement
switch(CommandSet.valueOf(String.valueOf(object)){
case Zcommand1: doStuffz1();break;
case Zcommand2: doStuffz2();break;
...
case ZcommandN: doStuffzN();break;
}
// other methods
void doStuffz1(){
...
}
...
void doStuffzN(){
...
}
}
Impossible: Java enums can neither extend another class nor be extended themselves.
They can however implement interfaces. Perhaps you can use that to your advantage.
There is something else about enums that may help you: enums are not immutable. You could change field values of the enums, however that would change them for the whole JVM.
Another approach maybe to pass your subclass instances into a method of the enum and have the enum use your subclass as a call back to get different functionality out of an enum for a different user of the enum.
Nope, you can't do that.
Java Enums run out of gas very quickly & definitely, when you want to add/extend more definitions or instantiate the enum instances, at a later time. (eg load them from database, configure them in an instance method, not just statically.)
Behaviour/ or logic in Java enums is kinda limited too -- you can define & set properties, but only what's statically initializable, and logic seems basic (you end up mainly just comparing references or ordinals, with the other defined enum constants).
What you can do:
You can implement an ancestor Command or AbstractCommand class, with a integer Code, and then subclass it to define concrete values/ additional codes/ load or configure instances, etc.
For further benefit, you get efficient switch & despatch (by Code) plus the ability to define further details/properties, instantiate commands as-needed, etc.
Essentially, this is how you used to define an Enum before Java supported them. Though you may be using them as value objects, rather than strictly static.
My expertise:
I've done extensive compiler & type-system work, tried enums for file-types and associated data/behaviour.. explored the outer limits, and reached the definite boundaries.
I also like being able to instantiate & return a new UnknownFileType("") as an answer, too. Enums can't do that.
Example:
(We'll despatch by String, not int -- since your code appears to be using Java 7. This makes command resolution easier, than requiring both a syntactical "name" and an internal integer "code".)
public static class Command {
protected String code;
protected String desc;
public String getCode() {return code;}
public String getDesc() {return desc;}
public Command (String code, String desc) {
this.code = code;
this.desc = desc;
}
public String toString() {return code;}
}
public class StandardCommands {
public static Command READ = new Command("READ", "read a record");
public static Command CREATE = new Command("WRITE", "create a record");
public static Command EDIT = new Command("WRITE", "modify a record");
}
public class FurtherCommands extends StandardCommands {
public static Command LIST = new Command("LIST", "list all records");
}
public class QueryCommands extends FurtherCommands {
public static class QueryCmd extends Command {
protected String search;
public String getSearch() {return search;}
// constructor..
}
public static QueryCmd QUERY_EXAMPLE = new QueryCmd("QUERY", "example", "query for specified string");
public static QueryCmd createQuery (String search) {
return new QueryCmd( "QUERY", search, "query for specified string");
}
}

Extending enums

I have a number of enums that each have the same fields and the same methods.
public enum AddressSubType {
DOM("dom"), INTL("intl"), POSTAL("postal");
private final String keyword;
private AddressSubType(String keyword) {
this.keyword = keyword;
}
public String getKeyword() {
return keyword;
}
#Override
public String toString() {
return keyword;
}
}
public enum EmailSubType {
INTERNET("internet"), X400("x.400");
private final String keyword;
private EmailSubType(String keyword) {
this.keyword = keyword;
}
public String getKeyword() {
return keyword;
}
#Override
public String toString() {
return keyword;
}
}
Is there a way for these enums to share the fields and methods (like a parent class)? I know that it's not possible to extend enums. Thanks.
You could create a Value class
public class Value {
private final String keyword;
private Value(String keyword) {
this.keyword = keyword;
}
public String getKeyword() {
return keyword;
}
#Override
public String toString() {
return keyword;
}
}
Then you can create Classes with public static final values like this :
public class AddressSubType extend Value {
public static final AddressSubType DOM = new AddressSubType("DOM");
public static final AddressSubType INTL = new AddressSubType("intl");
...
private AddressSubType(String keyword) {
super(keyword);
}
}
I would probably combine them into a single enum object where some are initialized with an "Postal" flag set to true and some have the "email" flag set to true since the two are really just different "types" of addresses.
You can then have it return iterators for either if you wish to access them separately or you can iterate over the whole thing.
You may also find some of the rest of your code becoming simplified, for instance just having a collection of "Address"es and checking at runtime to see if a given address is email or postal.
But it depends on how similar they really are.
You can declare an interface that they both can implement. This would allow you to pass either enum type as an argument to a method that only cares about specific methods on that inerface. However, this will only allow you to "share" the method signatures, not the fields or the method implementations.
If your enums are as trivial as in the given example, you don't have any significant amount of code repetition, so this probably isn't a problem. If you find that your methods have more complex, repetitive code, you should consider delegating that responsibility to a separate class.
If you really want to model an inheritance pattern (e.g. EmailAddress "is a" Address), then you'll need to get away from enums. You could just use some static fields to simulate the enum pattern, but have each of them be an instance of a specific class.
I will be the one to say it. This is an awful idea.
You should use enum types any time you need to represent a fixed set of constants. That includes natural enum types such as the planets in our solar system and data sets where you know all possible values at compile timeā€”for example, the choices on a menu, command line flags, and so on. source
The enum does not care about anything else except the hard coded values inside. Typically when one decides to group things in an Object Oriented way, they make sure that all of the objects are related. By virtue of being an enum these files are no more related than two classes that are subtypes of Object. If you are looking to have shared functionality between all enums in your domain you will want to look at some static functions, or a utility class as it is often referred to (this has its own series of issues at the end of the day). Essentially the class will have a series of functions that encapsulate all the shared logic, the signature will generally look like so:
function foo(Enum enumeration)
There's not much you can do in this case, and even in a more complex example, the best place to put common code might be in a utility class that all the enums could use, or in a separate class that would be included in the enums via composition (each enum would have an instance of that class, perhaps called Keyword).
If the code for the toString method were complex and you didn't want to restate it in each enum, or move it to a contained object, Java 8 has a mechanism that you could use. It is overkill in this example. You could define an interface that your enums would all use. The state (keyword) must still live in your enums, since interfaces cannot have state, but starting with Java 8 you can provide default implementations of methods:
public interface Common {
String getKeyword();
String toString() default {
return getKeyword();
}
String toDescriptiveString() default {
char firstLetter = getKeyword().charAt(0);
boolean vowel =
firstLetter == 'a' || firstLetter == 'e' ||
firstLetter == 'i' || firstLetter == 'o' ||
firstLetter == 'u' || firstLetter == 'x';
// the letter x is pronounced with an initial vowel sound (eks)
return (vowel?"an ":"a ") + getKeyword() + " address";
}
}
Your enums would implement this interface:
public enum AddressSubType implements Common {
DOM("dom"), INTL("intl"), POSTAL("postal");
private final String keyword;
private AddressSubType(String keyword) {
this.keyword = keyword;
}
#Override
public String getKeyword() {
return keyword;
}
#Override
public String toString() {
return Common.super.toString();
}
}
public enum EmailSubType implements Common {
INTERNET("internet"), X400("x.400");
private final String keyword;
private EmailSubType(String keyword) {
this.keyword = keyword;
}
#Override
public String getKeyword() {
return keyword;
}
#Override
public String toString() {
return Common.super.toString();
}
}
Notice the strange new syntax in the toString methods. The rule for default methods in interfaces is that method resolution always prefers class methods over interfaces. So even though we provide a default implementation of toString in Common, the one in the enum will take precedence, and the one in Object would if there wasn't one in the enum. So if you want to use a default method from an interface that supersedes one of the methods from Object (like toString, or hashCode, or equals), then you have to call it explicitly with this new interface.super.method() syntax.
We don't have to jump through any extra hoops for the toDescriptiveString method, though. That one is brand new in interface Common, and it isn't provided by our enums, so they get the default implementation provided by the interface. (If they wanted to override it with their own method, they could, just like any other inherited method.)
We can use the default methods like any other methods of an object, of course:
public class Test {
public static void main(String[] args) {
for (AddressSubType a : AddressSubType.values()) {
System.out.println(a.toDescriptiveString());
}
for (EmailSubType e : EmailSubType.values()) {
System.out.println(e.toDescriptiveString());
}
}
}
Which prints out:
a dom address
an intl address
a postal address
an internet address
an x.400 address
In this case, however, if it wasn't for the rather verbose toDescriptiveString method, the enum classes wouldn't be a bit shorter with interface Common than they would be without. Default methods in interfaces will really shine when it comes to adding new functionality to existing interfaces, something not possible without breaking all implementers of an interface in previous versions of Java.
All of this is based on the as-yet-incomplete Java SE 8 with Lambda. You can download a pre-release build, but be aware that it is a work in progress.

Getters/setters in Java

I'm new to Java, but have some OOP experience with ActionScript 3, so I'm trying to migrate relying on stuff I know.
In ActionScript 3 you can create getters and setters using the get and set keywords, meaning you create a method in the class and access data through a property of an instance of that class. I might sound complicated, but it's not. Here's an example:
class Dummy{
private var _name:String;
public function Dummy(name:String=null){
this._name = name;
}
//getter
public function get name():String{
return _name;
}
//setter
public function set name(value:String):void{
//do some validation if necessary
_name = value;
}
}
And I would access name in an object as:
var dummy:Dummy = new Dummy("fred");
trace(dummy.name);//prints: fred
dummy.name = "lolo";//setter
trace(dummy.name);//getter
How would I do that in Java?
Just having some public fields is out of the question.
I've noticed that there is this convention of using get and set in front of methods, which I'm OK with.
For example,
class Dummy{
String _name;
public void Dummy(){}
public void Dummy(String name){
_name = name;
}
public String getName(){
return _name;
}
public void setName(String name){
_name = name;
}
}
Is there an equivalent of ActionScript 3 getter/setters in Java, as in
accessing a private field as a field from an instance of the class, but having a method for implementing that internally in the class?
Nope. AS3 getters and setters are an ECMAScript thing. In Java, you're stuck with the getVal() and setVal() style functions--there isn't any syntactic sugar to make things easy for you.
I think Eclipse can help auto-generating those types of things though...
Your Java code is fine, except that you would, want to make _name private.
There are no get and set keywords in Java as in your AS3 example. Sorry, it doesn't get better than what you're doing already.
Corrected code:
class Dummy {
private String _name;
public void Dummy() {}
public void Dummy(String name) {
setName(name);
}
public String getName() {
return _name;
}
public void setName(String value) {
_name = value;
}
}
Sadly, no, there isn't the equivalent language-level support in java.
The get* and set* patterns though are so established in java culture that you'll find strong IDE support for them (e.g., eclipse will make them for you automatically), and if you're working in something that uses the expression language first made for jsps (EL), then you'll be able to use the property notation to access getters and setters.
I would consider not having the getter or setter as they don't do anything in your case except make the code more complicated. Here is an example without getters or setters.
class Dummy {
public String name;
public Dummy(String name) { this.name = name; }
}
Dummy dummy = new Dummy("fred");
System.out.println(dummy.name);//getter, prints: fred
dummy.name = "lolo";//setter
System.out.println(dummy.name);//getter, prints: lolo
IMHO Don't make things more complicated than you need to. It so often the case that adding complexity will suffer from You-Aint-Gonna-Need-It
An IDE-independent way is to use Lombok, an annotation-based library that generates getters, setters, and even equals() and hashcode(). It does this for the compiler, but not in the source file, so you don't have to look at the methods, just use them.
In Java, the only option you have without exposing the internals of your object is to make your own getters and setters as you have in your example.
The convention is to prepend get or set in front of the field which is being altered. So, as in your example, the field name would have getName and setName methods as their corresponding getter and setter, respectively.
Also before adding setters and getters, it might be a good idea to ask yourself why are you exposing the internal data of the Object in question.
I suggests you read this article -
http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html

Categories