How to expose an enum to public API without the implementation? - java

I have a class which has a property whose type is an Enum. Example:
enum CarType {
TOYOTA("Japan"),
AUDI("Germany"),
BMW("Germany");
public final String country;
private CarType(String country) { this.country = country; }
}
class Car {
private CarType type;
public CarType getType() { return type; }
}
The class Car is part of a library, and I would like to expose its functionality, so I create an interface which will be part of the public API, and have the class Car implement it:
interface ICar {
CarType getType();
}
class Car implements ICar {
private CarType type;
#Override public CarType getType() { return type; }
}
The problem with this approach is that this would require the whole CarType enum to be published. The CarType enum might contain additional attributes and methods which I do not want to expose / publish (country in this example).
What can I do if I want to hide the implementation of CarType but I still want to expose the possible values (the declared enum values) in a way so that the API users can reference them in switch and if statements like this:
ICar car = ...; // Get an instance somehow.
if (car.getType() == CarType.TOYOTA) System.out.println("It's Toyota.");
Making the additional attributes and methods protected or private is not a good solution because then other parts of the library would also not be able to reference to them.
Are there any good alternatives to this problem if I want to keep using Enums?

Although a late one wanted to add my thoughts -
enums can also implement an interface where you can expose only the require details:
public enum CarType implements ICarType {
...
public String getTypeName(){
return name();
}
}
public interface ICarType {
public String getTypeName();
}
So that you plan to use it in if()/switch
ICarType carType; //Not referencing the enum
if("TOYOTA".equalsIgnoreCase(carType.getTypeName())){
print("Toyota....");
}

You can provide Enum for public API, and convert it to another Enum for private usage.
E.g. use a Map, where key is public Enum instance and value - private Enum instance.
The problem is that you have to convert data each time the API is called. May require change in many places.

protected, private and package-private are the main tools you are provided with for this. If you think about your class hierarchy enough you can probably do something using them.
You should consider composition. Have a TypeDetails class, and have each member of the CarType contain a TypeDetails member. You can then restrict access to the TypeDetails getter to only those people who are supposed to access it while having the TypeDetails itself visible to all the parts of your library.

If it is strictly necessary to hide the country attribute to user code, you can go for standard visibility (attributes declared without public, protected or private qualifier, those attributes would only be visible for classes in the same package). I hope this to be useful, but I am aware that is only a patch.
Anyway I cannot fully understand your design and necessities, so probably you have no other option, but maybe what you need is a redesign with encapsulation in mind if you want to protect your code from API misuse

Related

Code repetition vs readablility

I have multiple services (in Spring MVC) that are children of a global Service. So I need to know about the best practice (or your opinions) with multiple methods with this example:
//Domain classes
public class MyParentObject{}
public class MyObj extends MyParentObject{}
//Services
public class MyParentObjectServiceImpl implements MyParentObjectService{
#Override
public MyParentObject findObjectByProp(String prop, String objectType){
//myCode (not abstract class)
}
}
public class MyObjServiceImpl extends MyParentObjectServiceImpl implements MyObjectService{
private myObjType = "MyObj";
#Override
public MyObj findMyObjByProp(String prop){
return (MyObj) super.findObjectByProp(prop, this.myObjType);
}
}
And in this approach, I use calls like this:
MyObj foo = myObjService.findMyObjByProp(prop);
So I need to know if this approach is "better" or more apropiate that calling directly the parent method with the second parameter. E.g:
MyObj foo = (MyObj)myParentObjectService.findObjectByProp(prop, "MyObj");
..and avoiding the creation of second methods, more specific. It is important to know that the children services will be created anyway, because we have lot of code that is specific of a domain objects.
I have the idea that the first approach is better, because is more readable, but I need to support that decision with some documents, blog, or opinions to discuss this designs with my colleagues.
This looks like a tagged class hierarchy. It's difficult to comment on the value of this design in general without knowing the details. However, a slightly different approach that I would recommend is to generify your base class to gain a little bit of type safety.
In particular:
public /* abstract */ class MyParentObjectServiceImpl<T extends MyParentObject>
implements MyParentObjectService{
MyParentObjectServiceImpl(Class<T> type) { this.type = type; }
private final Class<T> type; // subclasses provide this
#Override
public T findObjectByProp(String prop){
//you can use type for object specific stuff
}
}
public class MyObjServiceImpl extends MyParentObjectServiceImpl<MyObj>
// You might not need this interface anymore
// if the only method defined is findMyObjByProp
/* implements MyObjectService */ {
MyObjServiceImpl() {
super(MyObj.class);
}
#Override
public /* final */ MyObj findMyObjByProp(String prop) {
return (MyObj) super.findObjectByProp(prop, this.myObjType);
}
}
You definitely gain in type safety (casting will only appear in the base class), you get rid of the "tags" (the strings that identify the different objects) and possibly reduce the number of classes/interfaces required to implement the whole hierarchy. I successfully used this approach several times. Note that this works best if the base class is abstract. Food for thoughts.

Chaining Enumerations for hierarchical naming structures?

Since I have a terrible memory, I like to put all the detnd I ails of data objects into enumerations, so I can use code completion in the IDE adon't have to keep referring back to get the name of a table or the name of a field. Usually I use some type of class containing only Enums for the purpose.
Lets say I have table of "Domains" (database source) "Tables" and "Fields" that look something like this:
public class DataObjectNames {
public enum Domains {
Domain1,
Domain2;
}
public enum Domain1Tables {
Customers,
Orders;
}
public enum Domain2Tables {
OrderItems,
Shipments;
}
public enum CustomerFields {
id,
email;
}
public enum OrderFields {
id,
customerId;
}
//fields for OrderItems and Shipments . . .
}
But suppose I wanted to be able to do something like:
Domain1.tables().Customers.fields(). //code completion supplies choices?
What I would like ot happen after I type the period is for autocomplete to provide a choice between .id and .email, much the same as it would if "fields" returned an object with two methods, or if I just typed
CustomerFields.
in the IDE.
In order for that to happen, it seems to me I somehow need to return not a specific instance of an enumeration, but the enumeration itself. I've tried various approaches like this:
public enum Domains {
Domain1 {
#Override
public Enum<?> tables() {
return Domain1Tables.foo();
} //Is there a method that will return the enum itself?
},
Domain2 {
#Override
public Enum<?> tables() {
return Domain2Tables.foo();
};
public abstract Enum<?> tables();
}
But of course I haven't been able to find a funciton foo() that returns the enum class itself.
Any thoughts?
You can't do this with enums because Java's class model doesn't work the way you would need in order for this style to work.
I haven't been able to find a function foo() that returns the enum class itself.
Returning the enum class itself is easy, you just do Domain1Tables.class, but that won't give you the completion you want because what it gives you is a Class<Domain1Tables> object, and that object doesn't have fields named Customers and Orders.
You want to be able to treat the "Domain1Tables" class as if it's an object and refer to the enum constants (which are effectively static final fields) as if they were members of that object, but Java simply doesn't do that.
If you give up on using enums for it, then you can simply have:
public class DataObjectNames {
public class Domains {
class Domain1 {
class Tables {
class Customers {
public static final String id = "id";
public static final String email = "email";
}
}
}
}
}
but in that case DataObjectNames.Domains.Domain1 wouldn't be a valid expression anymore (because it reference to a class scope, but not to an object.
There's probably a solution to what you're trying to do, but without more context I can provide anything more details than what's above.

Making a code using enum generic

I have a code which was initially designed for just a single team where they were passing an enum [which stores list of tasks] to an api. This api then progates the use of this enum to many other classes.
Now i have a task where this code needs to be used by multiple teams and they can pass there own set of tasks in form of enums.
Given the current implementation i dont think it is feasible to support multiple teams which completely overhauling the code because enum's cannot extend other enums.
Is there any way to implement this without massive changes?
But... enums can implement interfaces, for example:
public interface Task {
int getPriority(); // just for example
// plus whatever methods define a task
}
public enum Team1Task implements Task {
Task1(1),
Task2(3);
private final int priority;
private Team1Task(int priority) {
this.priority = priority;
}
public int getPriority() {
return priority;
}
}
Now we can employ java generic kung fu to specify a generic parameter bounded to a suitable enum:
public class TaskProcessor<T extends Enum<T> & Task> {
public void process(T task) {
// do something with task
}
}
To use it:
TaskProcessor<Team1Task> p = new TaskProcessor<Team1Task>();
p.process(Team1Task.Open); // will only accept a Team1Task instance
FYI, as a curiosity of generics, you can alternatively use this bound to achieve the same thing:
public class TaskProcessor<T extends Enum<? extends Task>> {
Although I can find no practical difference in effect, I find it lacks the clarity and familiar pattern of the intersection bound above. For more on this see this question.
It is comparatively easy to make much of the work around enums generic.
Here's a severely cut-down example. It defines a generic database Table class that takes an enum Column as its defining type. The enum defines what columns are in the table. The defining type is an enum that also implements an interface which is a really useful trick.
public class Table<Column extends Enum<Column> & Table.Columns> {
// Name of the table.
protected final String tableName;
// All of the columns in the table. This is actually an EnumSet so very efficient.
protected final Set<Column> columns;
/**
* The base interface for all Column enums.
*/
public interface Columns {
// What type does it have in the database?
public Type getType();
}
// Small list of database types.
public enum Type {
String, Number, Date;
}
public Table(String tableName,
Set<Column> columns) {
this.tableName = tableName;
this.columns = columns;
}
}
You can now create your real table with something like:
public class VersionTable extends Table<VersionTable.Column> {
public enum Column implements Table.Columns {
Version(Table.Type.String),
ReleaseDate(Table.Type.Date);
final Table.Type type;
Column(Table.Type type) {
this.type = type;
}
#Override
public Type getType() {
return type;
}
}
public VersionTable() {
super("Versions", EnumSet.allOf(Column.class));
}
}
Note that this is a truly trivial example but with a little work it is easy to move a lot of your enum work into the parent class.
This technique does retain the type-safety checks you get when using generics.
Enums can implement interfaces. I would recommend coming up with a reasonable interface for the task. make your enum implement the interface and your code will continue to work just fine. other teams can use whatever interface implementation they desire (their own enum or something else). (note, without code it's hard to make very explicit recommendations).
You probably should not use enums for this, but if you want, you can implement logic in helper class, or set of classes that extend each other, and make enums a thin wrappers saround it:
public enum MyTaskEnum {
A, B, C;
private final TaskEnumHelper helper = new TaskEnumHelper();
public void foo (int x, int y)
{
helper.foo (x, y);
}
}

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");
}
}

Java: force implementor of an interface to have an immutable name field?

Requirement: I'd like all implementations of an interface to have a well-defined name.
Initially, I thought:
interface Fruit {
public String getName();
}
But this allows the user to have a field that is modified at run-time. I want to have an immutable name that is defined before compile/build time.
I've been toying with a couple of other ways to do it, but each has a limitation.
1) Give the name a type, which has slightly more control than free-form strings:
interface Fruit {
public FruitName getName();
}
abstract class FruitName {
public final String NAME;
public FruitName(name) {
this.NAME = name;
}
}
A user of this class will look like this:
class AppleFruitName extends FruitName {
public AppleFruitName() {
super("apple");
}
}
class Apple implements Fruit {
public FruitName getName() {
return new AppleFruitName();
}
}
2) Force an implementor of Fruit to annotate the name with something:
class Apple implements Fruit {
#FruitName
public static final NAME = "apple";
...
}
Clearly this implementation is far cleaner than (1), but I'm not sure if this is possible in Java? How do you get compile/build to fail if #FruitName is not present?
An easy way to do this - without aop, compile time weaving, runtime annotations, scanning at runtime.. etc is to encapsulate this behaviour in an abstract class:
interface Fruit {
public String getName();
}
abstract class FruitImpl {
private final String name;
public FruitImpl(name) {
this.name = name;
}
public final String getFruitName(){
return name;
}
}
So at construction time each implementation will be forced to pass in its name and it will not be able to alter it (unless the user is being intentionally malicious). This meets the what the wording of the question suggests.
There is a difference though because some the suggestions seem to assume that all implementations of the interface will have the same name - though the question doesn't state that. Is the idea that these implementations will be singletons?
Alternatively, you could use the decorator pattern to wrap the implementation and retrieve the field value once and then always return that value later, like this:
class FruitWrapper implements Fruit{
private final String name;
public FruitWrapper(Fruit fruit) {
this.name = fruit.getFruitName();
}
public final String getFruitName(){
return name;
}
}
So you can use it everywhere you would use fruit and it will guarantee to always get the same value.
This way you move the immutability into a class you control.
There are several options to enforce this.
At build time you could write tests for each of the Fruit classes that look for a field that satisfies your requirements.
At build time you could write a single test that goes through your entire classpath and verifies that each Fruit classes satisfies your requirements. A library like Reflections could help you to achieve this.
At compile time you could process an Annotation. I am not sure how you would make sure that each of your classes had an Annotation (as opposed that each class that contains an Annotation is one of the classes in your set.)
At implementation time, as a slight variation on your request, you could use an abstract class instead of an interface and require all implementors to hand you the fixed data in the constructor. That way, you have absolute control over the behaviour.
At runtime, while the application launches, you could check that all implementing classes satify your requirements in the same way an integration test would do it. In a scenario where third parties contribute to your API, this might be the last-stop option if you absolutely have to check it.
I think it is best to use tests for this. You'll have all the certainty you need with far better feedback and much less effort.
If tests are not an option, because you can't control the implementers, I'd go for the abstract class with enforcement during launch as a last resort.
Aren't you confusing static and final?
abstract class FruitName {
private final String name;
public FruitName(String name) {
this.name = name;
}
}
This is the best you can get in terms of interfaces/classes. You can also use custom annotation, but in slightly different way:
#FruitName("apple")
class Apple implements Fruit
And also consider using simple class name:
Fruit fruit = new Apple();
fruit.getClass().getSimpleName(); //"Apple"
But if you depend on class names somewhere, simple refactoring will ruin other parts of the code. So I would consider annotation more stable.
Bonus: your problem is easily solvable in scala:
trait Fruit {
val name: String //abstract AND final
}
class Apple extends Fruit {
val name = "apple" //you MUST implement this
}
If you don't "implement" val name (actually it is an immutable field), compiler will insist on marking Apple abstract.
you should be able to do it with aspectj and compile time waving

Categories