aspose file tools*
The moose likes Java in General and the fly likes List of Enum Types Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "List of Enum Types" Watch "List of Enum Types" New topic
Author

List of Enum Types

Sangel Kapoor
Ranch Hand

Joined: Jan 12, 2013
Posts: 84

Hello Geeks

Problem Statement : I am having Car class which contains various types of enums as follows.


Class Car

enum Engine { X,Y,Z}
enum Stearing { A,B,C}
enum Tyre {P,Q,R}



Problem : I want that client calls the getFilterType() method and i am able to return the types of enums i defined within the class. So that client is unaware of the number and can just iterate over the returned list and put .values over the returned items and gets the various values supported by each type of enum type defined within the class.

So i tried something like this



It is not working......




I want client of the above class to do something like this




Regards
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39869
    
  28
What do you mean by not working?
Sangel Kapoor
Ranch Hand

Joined: Jan 12, 2013
Posts: 84

I mean i expected something like that in Java, but it seems like it does not support , compiler is not much happy with my expectations.

In a nutshell, i have a problem in my hand and i dont know how to solve the same.
Matthew Brown
Bartender

Joined: Apr 06, 2010
Posts: 4467
    
    8

Well, the reason that doesn't work is that Engine, Tyre etc aren't variables, so you can't add them to a collection. Also, even if you could you'd run into another problem. values is a static method added to each enum, but not declared in the Enum class itself. So you can't call it on an Enum reference, and it wouldn't work polymorphically if you could.

I think you might be able to do what you're trying to do using reflection, but it won't be particularly pretty. I'm also not convinced it would be the best solution for the problem you're trying to solve, but we don't know enough about that to say. But if I was trying to get this approach working, I'd be trying something like this (with the caveat that none of this is tested):

First, get the method to return a List of Class objects representing each enum:
At the client side, you'd need to use reflection to try and find the values method attached to each class (look at Class.getMethod) and invoke it (look at Method.invoke). I haven't thought it through enough to tell if the generic types will cause you problems, though.
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19762
    
  20

You can't do exactly what you want, as you cannot call a static method on a reference and expect it to work for the actual class of that reference. Static methods only work on the reference type.

However, java.lang.Class does have a utility method for you. If you return a List<Class> you can do what you want:


SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
How To Ask Questions How To Answer Questions
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19762
    
  20

Heh. It looks like Matthew had the same idea, but the getEnumConstants() method will handle the reflection part for you.
Sangel Kapoor
Ranch Hand

Joined: Jan 12, 2013
Posts: 84

Thanks Rob and Matthew.....

Since i want to model this problem in a better way..... I don't know how expert programmers will design the solution for this, so if you could help me in giving me general idea , i would highly appreciate :-)

Problem : I have various objects in my application for a Shop, such as TShirts, Jeans, Trouser, Cap, Hats, Shirts and so on so forth.... Now user is shown with a "Filter" screen where he can choose to refine his results for each type. For instance , he wants all Tshirts for XYZ brand and XL size.

Tshirt can have different filters from Jeans .

So what i did is , i made POJOs for Tshirt. Jeans etc.

Tshirt has the following POJO definition

Similar is the definitions for Jeans and other items in the store.

Since client class has to show filter to the user for each type (and they can vary for Tshirt , jeans and others ) . I wanted client class to call Tshirt.getFilters() something to retrieve all the filters (defined as enums in Tshirt class) ie . Brand , Fabric, Size etc. And then client class can put .values something to get the all types of possible BRands , Fabric, Sizes for tshirt.

With this design i though it would be clean interface for the Client class to have calls something like this

Tshirt.getFilters() // Retrieveing Filters for Tshirt
Jeans.getFilters() // Retrieveing Filters for Jeans

With that i wanted to have retrieved list to be generalized enough so that client class code does not care whether it retrieved filters from Jeans or from Tshirt or from other. It all knows is to iterate over the retrieved list , put .values on each item and display it to the user.

Thanks and Warm Regards
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 8244
    
  23

Sahil Rally wrote:Problem : I want that client calls the getFilterType() method and i am able to return the types of enums i defined within the class. So that client is unaware of the number and can just iterate over the returned list and put .values over the returned items and gets the various values supported by each type of enum type defined within the class.

It seems to me that you're already getting good advice about the mechanics, but my question is: Why are you trying to do this?

Trying to get a list (and I suspect it should probably be a Set, not a List) of types defined in a program sounds like trying to create a language inside a language - and that's fraught with complications. And the fact that you're using enums to start with suggests that this is not what you want to do anyway.

Furthermore, ploughing all your enum values into a single collection seems to me to destroy the whole reason for differentiating them in the first place, and is likely to lead to dispatch code - which goes against everything that OO is all about.

My suggestion: back up and explain what you're trying to do, rather than how you're going to do it. Then, maybe, we can offer some better advice.

Winston

PS: Please DontWriteLongLines. I've broken yours up this time.

Isn't it funny how there's always time and money enough to do it WRONG?
Articles by Winston can be found here
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 8244
    
  23

Sahil Rally wrote:With that i wanted to have retrieved list to be generalized enough so that client class code does not care whether it retrieved filters from Jeans or from Tshirt or from other. It all knows is to iterate over the retrieved list , put .values on each item and display it to the user.

Aha! Finally, a proper problem description.

Simply put: You can't get there from here; by which I mean that you can't do what you want the way you've set it up.

Enums are designed for constants, but you're using them to define values - and more specifically, Sets of values that may change over time.
You might be able to get some of the way there by defining interfaces that your enums implement, but basically you're not dealing with similar things.

Does a pair of Jeans have a Neck size or Sleeves? I doubt it.

My suspicion is that you want some sort of SelectionCategory interface that ALL your enums implement, and each of your clothing classes will need a method that returns a Set (not a List) of Selection criteria for itself, made up of the contents of its enums - if that's how you choose to hold them. In fact, I suspect you will need a Set of Sets.

All that said, I don't think that enums are a very good choice here; and furthermore, things like Brands should be defined outside any individual class.

Winston
Sangel Kapoor
Ranch Hand

Joined: Jan 12, 2013
Posts: 84

Hello

Let me try to explain again what i was confronted with and what i thought to make such a bad solution iff it seems. :-)

T-Shirt is attributed with
a) Neck type
b) Brand
c) Fabric Type
d) Color type
....

So i thought that TShirt should have all these as member Variables. I felt it as a bad idea for the client code to have a call something like this



simple alternative solution for avoiding mistakes by client code is to have public static final constants in the TShirt class as

so that client uses

But i thought that ,why should client code remembers that POLO is a type of Neck and not Brand. Client code can use the following illegitimate code

In order to avoid such problems and to make client class use my code in an elegant way, i thought of following two solutions.

1) One is to use enums inside Tshirt class so that Client class code uses the following with no confusions




2) Second approach could be to have various interfaces like NeckInterface , BrandInterface and so on
So that client code uses the following



Finally with just a random idea i thought of chosing "Enums" .


Now ofcourse ,

I can write various methods in TShirt class like
getTshirtFilterTypes();
getTshirtPossibleNeckTypes();
getTshirtPossibleBrandTypes();


and let the client call all these to make the "Filter User Interface " for the TShirt .

I was just trying to think of a solution that client code just bother to call one method

getTshirtFilters();

and whatever cliend code gets , it iterates over it and use some method on each item to have all the possible values it can take.
ie it gets { NECK, BRAND , COLOR, FABRIC }
It Iterates over this , use someMethod on each to get values that each of this can take.
NECK : <appied some method over it> gets : POLO, ROUND .....


------------------------------------------------------------------------------------------------------------------------------------------

Eventually i should ended up with TShirt having getTshirtFilters() method that is exposed to the Client code.


Things evolved in the project, now there are Jeans , Trousers as welll..... ahhh...not a problem , if i can achieve
solution for above, client can call Jeans.getJeansFilter() and Trousers.getTrousersFilters().


--------------------------------------------------------------------------------------------------------------------------------------------


If everything would get working , i will eventually make a superclass with having getFilter() method and let Jeans, Trousers, TShirt extend that superclass
and client code will just use getFilter() method on the type it gets. Polymorphism will do the rest of the magic .


I think that the benefit of the code of above type is as follows....

1) There are new TYPEs like neck type , color, brand that want to add , say Rating .

So all i have to do is to add new enum type in TShirt and add to the list being returned from getFilter() method. Client code dont need to bother , it does not break.

2) There could be new color of tshirts in the market.

In that case i just need to add that color in the already defined color enum to get the things work again with no client code being break.



May be there is a better way to solve the above problem which i am unable to think of... Please suggest !!!

Warm Regards
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 8244
    
  23

Sahil Rally wrote:May be there is a better way to solve the above problem which i am unable to think of...

OK, now we're getting down to the nub of your problem.

Good explanation BTW, because we can see what you're thinking; and now I can understand why you thought that enums might be a good idea - and they still might be - however, I think that deciding on them at this stage is leaping to an implementation (the how) before you've described exactly what you need to do.

Let me offer an alternative description of your problem, and you tell me if I'm wrong:
1. You have a bunch of items of clothing.
2. You have a bunch of things (brand, style, size, fabric etc.) that categorize those items.
3. Some of those categories (eg, neck style) are specific to a particular type of item; others (eg, brand) aren't - Armani, for example, make all sorts of clothes.
4. You want a way of creating selection lists (your "filters"), by category, that are specific to each item.
5. You want those filters to be generic enough so that they can be displayed with a single set of code.
(notice: no mention of enums or even Java classes yet)

The first thing that suggests to me is that you probably want two classes for each item of clothing (eg, a shirt):
  • One that encapsulates an individual shirt.
  • One that describes a shirt in general terms; probably including a factory method for creating individual shirts.
  • Now you could possibly put them both in the same class; but I'd say they're not the same thing - one is an inventory item; the other is a blueprint.

    And it's the blueprint class (Shirts?) that should contain your categories - be they enums or simply Sets - rather than your item class (Shirt).
    Furthermore, I think its the blueprint class that should contain the method to create your "filter"; and it should probably be the same method for all of them, ie, instead of:
    getTshirtFilters();
    which is type-specific, you'll want something more like:
    TShirts.getFilter();
    and the easiest way to ensure that is to have them all implement the same interface (Filterable?).

    I'd also consider creating a Filter class to hold your selection lists; and maybe even make it typed, viz:
    public class Filter<T extends Filterable> { ...
    and have it be responsible for displaying itself (or, probably better, providing methods that make it easy to display the contents).

    From your description, I also suspect that there is some hierarchy to your clothing items (or at least, their blueprints). For example, are Jeans not a type of Trousers? Only you can answer that; but I suspect they have a lot in common.

    Phew. A lot to think over ... and I bet it seems like I've muddied the waters rather than provided solutions.

    Unfortunately, that's the way it is with design, and it's especially why you don't want to tie yourself down to an implementation (like enums) until you're certain you have the requirements sorted out.

    Tip: Start slow. Try whatever you come up with out with maybe a couple of clothing items, each with a couple of categories, and build from there. And whatever you do, don't worry about any GUI stuff until you know that the selection process is working.

    I'd also say: forget about 'fabric' for a while; it's likely to be a tough one to implement. Stick to simple stuff like 'neck style's and 'inside leg' lengths to start with.

    HIH, and good luck. This is not a simple problem.

    Winston
    Sangel Kapoor
    Ranch Hand

    Joined: Jan 12, 2013
    Posts: 84

    Thanks Winston for your prolific tips and your description of my problem is 100% correct :-)

    Let me write what i have understood from your tips.

    1) (Important one) Keep your Implementation thoughts away while you think of the possible elegant solution and design .
    2) Tshirt entity should be represented by following classes in the project

    A) Tshirt Pojo : Having member variables which stores its state.
    B) Tshirt BluePrint class : Which contains Factory Method for Tshirt class and "Categories" such as "Neck Types" , "Colour" etc.
    C) Tshirt BluePrint Class : It contains the public method for the client code : getFilters() which it has to override since it implements Filterable interface.


    I will try to implement the code in above way.

    But there are 2 still things i will get confronted with again

    1) Even if BluePrint class contains the categories, what is the best way to return the List of Enum types or may be something else (if you think of differently ), so that client code
    just iterate over the list and have all the Categories and sub-categories. By Category i mean NECK and by sub-category i mean POLO,ROUND etc.


    For Client Code : the following code should work , no matter it is called on TShirt, Jeans or Trousers.




    Thanks and Regards
    Winston Gutkowski
    Bartender

    Joined: Mar 17, 2011
    Posts: 8244
        
      23

    Sahil Rally wrote:Let me write what i have understood from your tips.
    1) (Important one) Keep your Implementation thoughts away while you think of the possible elegant solution and design .
    2) Tshirt entity should be represented by following classes in the project
    A) Tshirt Pojo : Having member variables which stores its state.
    B) Tshirt BluePrint class : Which contains Factory Method for Tshirt class and "Categories" such as "Neck Types" , "Colour" etc.
    C) Tshirt BluePrint Class : It contains the public method for the client code : getFilters() which it has to override since it implements Filterable interface.

    Correct. Especially (1).

    With (2), you've introduced the word "pojo", which suggests to me that these objects may be persisted in a database. That introduces a layer that I hadn't considered when giving my advice; but I think it still holds true.

    But there are 2 still things i will get confronted with again...

    No you won't if you design before you code (and I have read the rest of your post).

    All of your concerns are about HOW: how do I iterate?; how do I deal with this...or that...? And that is all about how you're going to code it.

    And you know what? 99% of the time, it doesn't matter. Java is a rich language; and there are very few things that you can't do with it.

    Your design (if you get it right) will probably give you a good idea how to code it anyway; but until then, you need to chuck your computer (and especially Java) aside until you can explain what needs to be done, forwards, backwards and sideways - and preferably, in English (or your native language).

    Once you have that, HOW you do it (your code) is up to you. And when you get to that point (and I don't think you're there yet), you will probably discover that there are many ways to implement, so don't tie yourself down to anything specific just yet. The chances are also that, by the time you are ready to code, you will have put so much thought into it that the code itself will be a doddle.

    Stop coding (or thinking about code) and DESIGN.

    Winston
    Winston Gutkowski
    Bartender

    Joined: Mar 17, 2011
    Posts: 8244
        
      23

    Sahil Rally wrote:1) Even if BluePrint class contains the categories, what is the best way to return the List of Enum types or may be something else (if you think of differently ), so that client code just iterate over the list and have all the Categories and sub-categories. By Category i mean NECK and by sub-category i mean POLO,ROUND etc...

    Sorry. Kind of missed this in my previous reply; but I think I suggested a solution in my original post:
    Design a Filter class.

    For Client Code : the following code should work , no matter it is called on TShirt, Jeans or Trousers...

    Whoa hoss. You're getting ahead of yourself again.

    WHAT first; then HOW...

    Winston
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: List of Enum Types