• Post Reply Bookmark Topic Watch Topic
  • New Topic

Enums  RSS feed

 
nick woodward
Ranch Hand
Posts: 382
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've been side-tracked again..... this time by enums.....

I've a class Till.java, and an enum type 'Options', shown below:



At present the Till class just uses the above code in a method called 'printMainMenu'.

BUT.....

Now I'm thinking about how to use this enum class (and the optionNumber) in a more useful way, perhaps to help restrict the answer given by the user in response to being asked to pick an option in the Till class.

Is this the right way of thinking? Or should I just restrict the possible answers in a try-catch block in the Till class instead? the Enums are starting to confuse me...... Aren't they supposed to help with things like this?

Thanks!!
 
Campbell Ritchie
Marshal
Posts: 56525
172
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Have you been through the Java® Tutorials? Are you aware of methods to do with the ordinal in enums? Did you know that enum constants can be used in switch statements?

Try a few of those ideas.
 
Knute Snortum
Sheriff
Posts: 4274
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Or should I just restrict the possible answers in a try-catch block in the Till class instead?


It's a bad idea to use a try-catch block for code that's not "exceptional". You expect the user to make a mistake now and then, so code for it. Validate the user input, continue if it passes and re-ask the question if it doesn't.
 
nick woodward
Ranch Hand
Posts: 382
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
thanks for the help. and yeah, I think I was a little tired when I mentioned a try-catch block

so would I use a method in the enum class to validate the answer?

something like this:



or should i validate in the Till class?
 
Knute Snortum
Sheriff
Posts: 4274
127
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you ask the question, "Would I ever use this outside of the Till.java class?" I think the answer is no. If so, I would make the Options enum an inner class. Then validOptions() can be in either the enum or the Till class; it doesn't matter.
 
Campbell Ritchie
Marshal
Posts: 56525
172
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No.
Remember that enum has some constraints about how many members it can have. In your case it might have four, or four, or four. But not three or five. There must be a way to get a count of elements from an enum; go through the Java® Tutorials link again, the Java® Language Specification and the Enum<T> class and see whether there is anything helpful. If all else fails try
myEnum.values().length
That should give 4.
Now all you need is to get the number between 1 and 4 (or 0—3).
What is wrong with this?
 
nick woodward
Ranch Hand
Posts: 382
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:No.
Remember that enum has some constraints about how many members it can have. In your case it might have four, or four, or four. But not three or five.


I'm sorry, but I don't really understand. The enum is constrained to four options isn't it?

Campbell Ritchie wrote:There must be a way to get a count of elements from an enum;

Again, I'm not sure why? I'll have a look at those links you've mentioned, but I dont' see the flaw (yet) in what I posted, mainly because I haven't understood your first point.

Campbell Ritchie wrote:If all else fails try
myEnum.values().length
That should give 4.
Now all you need is to get the number between 1 and 4 (or 0—3).
What is wrong with this?


other than me being less comfortable with that approach, nothing that I can see. is it much better? just to clarify this is how i've done it:

Till.java:


Options.java


I'll get reading those links, but I think I've completely missed the point you're trying to guide me towards. Sorry!

Nick
 
nick woodward
Ranch Hand
Posts: 382
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Option o = Options.values()[i - 1];

ahhh. is this the difference? that it forces a type 'Option'?

i'm going to keep reading, but in all honesty that language specification was too hard (and i'm not useless at this now ), and the tutorial seemed a bit brief.....

i'm currently using K&B OCA study guide, but not sure if that's just going to get into much depth.
 
Campbell Ritchie
Marshal
Posts: 56525
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The four or four or four bit was a joke. Such jokes always seem to fall flat on the Internet.
Sending you to the JLS was so as not to do all the work myself. I suspected there might be nothing helpful there, but the idea was to make sure you knew whether there was a way to convert “four elements” to 4.
I know what “four” means. You know what “four” means. My little grandson before reaching the age of four told use earnestly that a square has four sides and they are all the same and held up four fingers thereby proving he knew what “four” means. But the computer does not know what “four” means. It can however understand 4. And the only way I found of getting 4 out of your enum was
Options.values().length
I had hoped there might be a more elegant way to do it like the Enum#count() method but that doesn't exist and we didn't find anything else appropriate.

Now you have got 4 and you know how to get an array of elements (they are officially called constants) out of your enum. Now you can iterate the array by using the indices 0, 1, 2, 3. You can ask the user to enter those numbers but most users prefer 1, 2, 3, 4, which is why you need the + 1 and the − 1 to convert it between 0‑based indices and 1‑based indices and vice versa. Now as long as the strange‑looking loop ensures that the user only enters a number between 1 and 4 inclusive, you can be completely confident that line 15 code will assign a valid Option to o. The only thing which can go wrong with that code is that the user enters something which isn't a valid int and you suffer an Exception at line 13. You may prefer to create the String output from the StringBuilder as a private static final field (i.e. a local constant).

There are all sorts of alternative ways to do things (there always seem to be lots of alternatives in computing).

It seems something not quite right repeatedly to traverse an array and see whether the number attribute (I would prefer a method to get that number.) is one of those given when you already know it has to be in the range 1…4 (or 0…3). Since you can get those numbers from the standard methods of the Enum<T> class, you can replace that number field with this sort of method in the enum:You can simply replace the valid index method with either version of the following:-You could create a constant in the enum if you prefer and use Option.SIZE elsewhere:As I said, all sorts of options.
 
Campbell Ritchie
Marshal
Posts: 56525
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
nick woodward wrote: . . . that language specification was too hard . . .
Sorry, should have warned you how difficult the JLS can be to read.
 
Campbell Ritchie
Marshal
Posts: 56525
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Knute Snortum wrote: . . . If so, I would make the Options enum an inner class.
Agree.
Then validOptions() can be in either the enum or the Till class; it doesn't matter.
Disagree. It looks to me definitely something associated with the Option enum, so it should be in Option.
 
nick woodward
Ranch Hand
Posts: 382
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:The four or four or four bit was a joke. Such jokes always seem to fall flat on the Internet.





anyway, i think i understand now! so other than the fact that my suggested code is a bit weird (cycling through each enum constant in the array and retrieving, without a method, the optionNumber member) there isn't anything particularly wrong with it?

i had actually tried to use .length - but came across a few errors, so just tried something else (knowing me i was probably using .length()). really useful looking at it that way though, especially using .ordinal(). i now understand your code a whole lot better. thanks for the detailed answer!!

just out of interest, what would be your approach to calling the Till.java method relevant to the chosen enum? using a switch statement (or similar) in the Till.java class, or overriding a method in each constant specific class body in Options.java? - hope that makes sense!!

thanks again, really appreciated!

nick

**edit: scrap the class body of each constant, will just pass the user input to a method in Options.java and make the relevant call from there i guess
 
Campbell Ritchie
Marshal
Posts: 56525
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If possible, it is more object‑oriented to put the logic into methods on the individual Option objects. Even if you make Options an inner class (good idea of PS's) … you can then call private methods of the Till class from inside Option objects.

As for length/length(): that is a notorious cause of confusion possibly caused by whoever wrote the first array code not communicating with whoever wrote the methods for the String class
 
nick woodward
Ranch Hand
Posts: 382
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:If possible, it is more object‑oriented to put the logic into methods on the individual Option objects. Even if you make Options an inner class (good idea of PS's) … you can then call private methods of the Till class from inside Option objects.


yeah, that's what i figured. prefer it that way tbh. keeping them in separate files for clarity, but suffering from a range of problems when trying to call:

<Till.java> public void createNewTransaction(){...} from <Options.java> public void runOption(int i) which is called from the constructor of the Till class using Options.runOption();


**edit: currently removed the override to get this straight in my head. i'm getting non-static method runOption(int) cannot be referenced from a static context Options.runOption(selection) - which makes no sense to me. i thought runOption was implicitly static, but obviously not, and i don't understand how calling it from the till constructor can be considered a static context??

*** ok, so the static context is the fact that Options.runOption (called in the Till constructor) is static. Options.NEW_SALE.runOption() compiles and runs. but this still seems confusing. so any method in the enum class that is non-static has to be called by referencing the specific constant? or the method has to be declared static to be called using the enum type only?

^ that's fine, so i now have to change the runOption() method in Options.java to be static, but that then means I can't override the method in each constant class body. AHHHHH!!!

*** new approach - create a local Option variable in the Till class...... and then call o.runOption().

Options.java

Till.java


The 'throw my toys out of the pram, delete all code and start again' option looms ever closer working!!! (but seems convoluted....)


As for length/length(): that is a notorious cause of confusion possibly caused by whoever wrote the first array code not communicating with whoever wrote the methods for the String class


this will definitely be a trap i fall into for years to come! haha
 
Campbell Ritchie
Marshal
Posts: 56525
172
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
My, your last post reads as though you had just overdosed on coffee (‍).

Surely you would call that method on an Option object (constant)? So it would not need to be static. I always get suspicious when I see the keyword static because I suspect somebody is not writing object coding (of course in Java8 you are allowed to write functional code too).
I suggest you go back and note what KS said earlier about inner classes. If Option is only used from the Till object, then make it a (preferably private) inner class. Read about inner classes in the Java® Tutorials. Let's see what I can remember about inner classes.
  • 1: The represent an intimate connection with the outer class: for example in a Binary Tree the inner Node class means that a Node is part of the tree.
  • 2: They aren't allowed static members.
  • 3: They don't use this normally; if you need a member of the surrounding class you write Outer.this.foo();
  • 4: might have got most of that wrong, so back to the Java Tutorials link!
  • So what about thisGo back to the Java® Language Specification link I gave you earlier, and there is an example with PLUS MINUS, number 8.9.3-3. Can you see the similarity to my example?

    Also nothing that I have written needs to be static.
    You can easily add back the constructor calls which you had in your original version of the enum if you need them.
     
    Campbell Ritchie
    Marshal
    Posts: 56525
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    You may need to write runOption as an abstract method in your enum too.
     
    Campbell Ritchie
    Marshal
    Posts: 56525
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Damn! Won't work. Because an enum constant is implicitly a static member of its class, you cannot use the this keyword. Have you tried a switch:you should never reach default.
     
    Darryl Burke
    Bartender
    Posts: 5167
    11
    Java Netbeans IDE Opera
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Campbell Ritchie wrote:Damn! Won't work. Because an enum constant is implicitly a static member of its class, you cannot use the this keyword.

    Isn't it rather that an enum declared within an outer class is implicitly static, hence a nested rather than an inner class?

    Another way to overcome that an inner enum, being static, cannot reference an enclosing instance is to pass the instance as a parameter.

    edit Made the overridden method abstract, as it should have been in the first place.
     
    Campbell Ritchie
    Marshal
    Posts: 56525
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Darryl Burke wrote: . . . Isn't it rather that an enum declared within an outer class is implicitly static, hence a nested rather than an inner class?

    Another way to overcome that an inner enum, being static, cannot reference an enclosing instance is to pass the instance as a parameter. . . .
    Yes, and the obvious solution about passing a Till method only occurred to me afterwards.
     
    nick woodward
    Ranch Hand
    Posts: 382
    12
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Campbell Ritchie wrote:My, your last post reads as though you had just overdosed on coffee (‍).

    Surely you would call that method on an Option object (constant)? So it would not need to be static. I always get suspicious when I see the keyword static because I suspect somebody is not writing object coding (of course in Java8 you are allowed to write functional code too).
    I suggest you go back and note what KS said earlier about inner classes. If Option is only used from the Till object, then make it a (preferably private) inner class. Read about inner classes in the Java® Tutorials. Let's see what I can remember about inner classes.
  • 1: The represent an intimate connection with the outer class: for example in a Binary Tree the inner Node class means that a Node is part of the tree.
  • 2: They aren't allowed static members.
  • 3: They don't use this normally; if you need a member of the surrounding class you write Outer.this.foo();
  • 4: might have got most of that wrong, so back to the Java Tutorials link!
  • So what about thisGo back to the Java® Language Specification link I gave you earlier, and there is an example with PLUS MINUS, number 8.9.3-3. Can you see the similarity to my example?

    Also nothing that I have written needs to be static.
    You can easily add back the constructor calls which you had in your original version of the enum if you need them.


    it was a mixture of coffee, a lack of sleep, and just typing as I went along. it was more a running dialogue by the end of it to help me keep track of what i was doing! apologies!

    anyway, am going to digest what you've suggested and see what i can come up with in the next few hours. although at first glance being implicitly static was what was causing me problems with calling and overriding the methods. i had tried what darryl suggested too with no luck. and obviously coffee hadn't helped...

    i'll have a look at inner classes like you suggest. and maybe write everything from scratch again

     
    Knute Snortum
    Sheriff
    Posts: 4274
    127
    Chrome Eclipse IDE Java Postgres Database VI Editor
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    There's a saying I used to hear about programming: When in trouble, run away. When in doubt, quit.

    It sounds terrible, but it emphasizes that sometimes it's better to just start over when your program isn't doing what you want.
     
    Campbell Ritchie
    Marshal
    Posts: 56525
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    nick woodward wrote: . . . am going to digest what you've suggested . . .
    Try sticking to the bits I actually got right

    By the way: if the enum inside the other class is implicitly static, you don't call it an inner class. You call it a static nested class/enum.
     
    Campbell Ritchie
    Marshal
    Posts: 56525
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I did manage to get it to work
    java Till
    Adding Stock on Till 1
    New Sale on Till 2
    Listing Stock on Till 1
    Trying to turn off Till 1
    Trying to turn off Till 2
    New Sale on Till 2
    Trying to turn off Till 2
    Listing Stock on Till 2
    Adding Stock on Till 2
    Adding Stock on Till 2
    New Sale on Till 2
    Trying to turn off Till 2
    New Sale on Till 2
    New Sale on Till 2
    Trying to turn off Till 2
    New Sale on Till 2
    New Sale on Till 2
    Adding Stock on Till 2
    New Sale on Till 2
    New Sale on Till 2
    Adding Stock on Till 2
    Adding Stock on Till 2
    New Sale on Till 2
    Trying to turn off Till 2
    New Sale on Till 2
    New Sale on Till 2
    New Sale on Till 2
    Listing Stock on Till 2
    Listing Stock on Till 2
    New Sale on Till 2
    New Sale on Till 2
    Adding Stock on Till 2
    Adding Stock on Till 2
    Listing Stock on Till 2
    Listing Stock on Till 2
    New Sale on Till 2
    New Sale on Till 2
    New Sale on Till 2
    Listing Stock on Till 2
    Trying to turn off Till 2
    New Sale on Till 2
    Trying to turn off Till 2
    Adding Stock on Till 2
    New Sale on Till 1
    Listing Stock on Till 1
    Listing Stock on Till 1
    Trying to turn off Till 1
    Trying to turn off Till 2
    Adding Stock on Till 2
    New Sale on Till 2
    Trying to turn off Till 2
    New Sale on Till 2
    Listing Stock on Till 2
    Adding Stock on Till 2
    New Sale on Till 2
    Listing Stock on Till 2
    Adding Stock on Till 2
    Listing Stock on Till 2
    Listing Stock on Till 2
    Trying to turn off Till 2
    Trying to turn off Till 2
    Note that the turn off method includes
    running = rnd,nextDouble < 0.9;
    … so there is only a 10% chance that it will actually turn off. The order of calls is random, hence the repetitions. The output differs from run to run.
     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!