• Post Reply Bookmark Topic Watch Topic
  • New Topic

How to pass a parameter to an object created in an enum.  RSS feed

 
Kendall Ponder
Ranch Hand
Posts: 205
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have received a lot of help from Sheriff Ritchie and others at How to decide if a method should be static and have come up with the following code to implement a menu. For the purposes of my question you probably only need to look at the enum and the executeMenuChoice() method.

My question is how to handle a situation where I have to pass a parameter to the objects stored in the enum. The Modify an Existing team choice in the menu above requires a team to be passed to the classes which modify a team. In the code below I used a factory (at least I think I did) to create the needed class. I passed the team to be modified to the factory via its constructor and the factory passed the team to be modified to the created class via the executeMenuChoice method. I was going to pass it in the constructor but if I understand correctly each of the menu objects in the enum will only be created once so I need to change a field in the object after it is created. As always any suggestions on how to improve the code will be appreciated.
 
Campbell Ritchie
Marshal
Posts: 56599
172
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Flattery will get you anywhere

You cannot pass information to a constructor of a enum element. You cannot call the constructor from outside the enum class. You can however pass information to methods of an enum element (officially called a constant). The Java™ Tutorials example shows weights being passed to methods of a Planet enum, which calculate the weight on different planets.

I am not convinced you have a factory there, but I may have forgotten my design patterns. A factory method (you can read about them in the 1st chapter of Effective Java™ by Joshua Bloch) creates an instance of a class and returns it. Factory methods may have to be called before there are any instances, so they are often static. They are often called instance getInstance newInstance instanceWithXYZandPQR valueOf or of. Their return type is the class they are creating (or a superclass). You can see examples 1 2 3

I am sure you can have mutable fields in an enum constant, but I don't think that is the intent behind enums; they are supposed to be constant so they should really not change their state. You appear to have the List of Teams; why don't you use that? You appear already to have methods which amend the List. Why not add methods to find a particular Team and then you can change its state.
Try this as an alternative to the method you wrote.Beware: unmodifiable does not mean immutable. It means read‑only. If you alter the List in its original location, or it you alter the state of any of the Teams in the List, those changes will be reflected in the unmodifiable copy.
 
Kendall Ponder
Ranch Hand
Posts: 205
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You cannot pass information to a constructor of a enum element. You cannot call the constructor from outside the enum class. You can however pass information to methods of an enum element (officially called a constant). The Java™ Tutorials example shows weights being passed to methods of a Planet enum, which calculate the weight on different planets.

I don't need to pass information to the constructor of the enum, I need to pass information to the the object stored in the enum.

I am not convinced you have a factory there, but I may have forgotten my design patterns.

I am sure you are right. It does what I want it to, but I will look more closely at how the factory pattern works and see if it fits here.

I am sure you can have mutable fields in an enum constant, but I don't think that is the intent behind enums; they are supposed to be constant so they should really not change their state. You appear to have the List of Teams; why don't you use that? You appear already to have methods which amend the List. Why not add methods to find a particular Team and then you can change its state.

I think that is basically what I did but it isn't obvious because I didn't show the object stored in the enum. I tried to just show the flow of the index to the list of teams below and left out the code which didn't affect it. I don't know if that makes it easier to follow or not. The object called from the enum (in the example below, ModifyTeamDescriptionMenu) has to have access to a field which either has the team to change or the index to the team to change. It seems to me I either have to pass it as a parameter or it has to be stored in a static field the object can access. As you pointed out in the other thread I will always get the same MenuObject for a given choice in the menu.


 
Kendall Ponder
Ranch Hand
Posts: 205
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:

Try this as an alternative to the method you wrote.Beware: unmodifiable does not mean immutable. It means read‑only. If you alter the List in its original location, or it you alter the state of any of the Teams in the List, those changes will be reflected in the unmodifiable copy.

So this does the same thing my method does correct? Is there a Collections method I should use to save any changes I make to the unmodifiable copy to the master list?

Thanks again for your time!
 
Campbell Ritchie
Marshal
Posts: 56599
172
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No, that method does not actually do the same as your method.
Your method returns a new List which is a “snapshot” of that List at the time the method is invoked; that new List is available for alterations anywhere. You can simplify that method:-Look up the ArrayList(Collection) constructor.

My method with unmodifiable Lists returns a “view” of the List of Teams, which (as the link I posted earlier says) is read‑only. If you try to add or remove Teams, you suffer an Exception. If you amend the original List, those changes are reflected in the unmodifiable version. If you are going to use the unmodifiable version frequently, consider caching the unmodifiable List so you can return the same reference and save memory. You can also return an unmodifiable “snapshot” by combining those two techniques:-Because the unmodifiable copy is of a local variable, you can never get access to it again to modify it.

If the Teams which are elements of that List are mutable, they remain mutable and changed state in one location will be visible in all other locations where that Team object is to be found.

Not sure just at the moment how to make a Team accessible to the enum element. But does the enum element require access to the Teams? Doesn't the menu require that access?
 
Kendall Ponder
Ranch Hand
Posts: 205
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:
You can simplify that method:-Look up the ArrayList(Collection) constructor.

Thanks! That simplifies things.
 
Kendall Ponder
Ranch Hand
Posts: 205
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If the Teams which are elements of that List are mutable, they remain mutable and changed state in one location will be visible in all other locations where that Team object is to be found.

So I can get the unmodifiable copy of the listOfTeams and then make changes to individual teams in the unmodifiable copy and the changes will automatically show up in the original list? That will simplify things.
 
Kendall Ponder
Ranch Hand
Posts: 205
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Not sure just at the moment how to make a Team accessible to the enum element. But does the enum element require access to the Teams? Doesn't the menu require that access?

Our basic structure is


The menu has a method which gets the desired enum from the user, and that enum is used to execute the next menuObject. When the user chooses to modify the team the first thing I want to do is find out which team they want to modify and then they choose how to modify it. I want them to be able to make several modifications on whatever team they choose so the team choice has to come before the menu choice. So after the menu is chosen it has to have access to the team. I did it with the following code:

newMenu holds one of the ModifyTeam menus. All of those menus have an executeMenuChoice(int teamToModifyIndex) method which allows them to get the team they need from the unmodifiable copy of the list as discussed above. I have gotten this to work (minus the unmodifiable copy of course). You could also have a static teamToModifyIndex field in the mainMenu to hold the Index and all of the methods could access it but I didn't think that was as desireable. I found this on StackOverFlow Removing Switch from an enum which I think is slightly different from how we are doing it. I need to look at it some more.
 
Campbell Ritchie
Marshal
Posts: 56599
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You have obviously put lots of work into researching your problem; that SO thread does make some helpful suggestions.
 
Kendall Ponder
Ranch Hand
Posts: 205
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Kendall Ponder wrote:
Campbell Ritchie wrote:
You can simplify that method:-Look up the ArrayList(Collection) constructor.

Thanks! That simplifies things.

This is saving lots of lines of code throughout my program. Thanks!
 
Kendall Ponder
Ranch Hand
Posts: 205
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
For those who are interested here is how I implemented the idea I found on StackOverflow which I referenced earlier in the thread Providing a factory method directly on the enum type.
I used the first answer, although it turns out he left out some curly braces. If you don't want to wade through the whole thing (I wouldn't) I would look at the executeMenu() method at line 83. There is a list of available teams and the ChooseATeamMenu() retrieves the index of the team the user wants. The getMenuChoice() method in the while loop uses the ModifyTeamChoiceMenu enum which corresponds to the users choice to return the needed menu class. Then you can use the overridden executeMenuChoice() to perform the correct task. I'm not sure this is easier to read than if I just used a switch statement but lots of experienced programmers say it is much easier to maintain and expand so I think it is worth knowing how to do. Thanks again to everyone who has helped me on this topic.

P.S. I haven't implemented the unmodifiable copy Sheriff Ritchie talked about but it is on my list of things to do.



Here is the entire ModifyTeamMenu class.



Here is the ModifyTeamDescriptionMenu class. The overridden executeMenu() method is on line 19.

Lastly, just in case someone wants to see it, here is the MainMenu class which instantiates the ModifyTeamMenu object.
 
Kendall Ponder
Ranch Hand
Posts: 205
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Just in case someone is interested in how I implemented all of the help I have received the latest code is at Baseball Simulation on GitHub. If anyone wants to run it the main() method is in the Baseball class in the controller package. The Create team and Modify team menus work. The first two choices just have stubs. I have added a second abstract method to my Player object which was fun! I did not use the unmodifiable copy of the team list because I needed a separate copy of the teams. I need the copy of the list to have copies of the teams and not the same teams. My goal is to have the first two options completed next week and then try to learn some swing by changing my text menus into GUI menus. Thanks again for all of you who have helped.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!