Creating a Java enum - java

I am told I need to create an enumeration Team with 2 values of Varsity and JV. Is this what it should look like? Do I need the constructor?
public enum Team {
Varsity, JV;
private String Level;
private Team(String studentLevel) {
Level = studentLevel;
}
}

It's almost correct: you need to pass values to the constructors, e.g. like this:
public enum Team {
Varsity("level_v"), JV("level_jv");
private String Level;
private Team(String studentLevel) {
Level = studentLevel;
}
}
Whether you need the constructor or not depends on whether your enum needs parameters/fields. You'd then set those fields with the constructor and since they shouldn't be changed in most cases, I'd declare them to be final as well, i.e. private final String level.

public enum Team
{
Varsity("someLvl"), JV("someLvl");
private String studentLevel;
Team(String studentLevel)
{
this.setStudentLevel(studentLevel);
}
public String getStudentLevel() {
return studentLevel;
}
private void setStudentLevel(String studentLevel) {
this.studentLevel = studentLevel;
}
}
You need to set the student level right away.

Related

Constructor Chaining with subclasses in Java

Just a question RE: Constructor Chaining in subclasses that I can't find a good answer on and I'm confusing myself a bit with.
I'm making a basic little Text Based RPG for some practice and I'm going through my constructors for an abstract class and have the constructors from 0-4 params chained together like below
abstract class Creature {
// Fields
private String name;
private int lifeForce;
private int strength;
private int agility;
// Constructors + Chaining
public Creature() {
this("Unknown")
}
public Creature(String name) {
this(name, 100);
}
public Creature(String name, int lifeForce) {
this(name, lifeForce, 10);
}
public Creature(String name, int lifeForce, int strength) {
this(name, lifeForce, strength, 10);
}
public Creature(String name, int lifeForce, int strength, int agility) {
this.name = name;
this.lifeForce = lifeForce;
this.strength = strength;
this.agility = agility;
}
My confusion is how best to format the constructors of a subclass of creature, for example this simple Person class introduces two new fields. There's definitely too much repetition if I write the constructors like this
// Constructors + Chaining
public Person() {
super("Unknown");
this.skillClass=new Mage();
this.dialogue="...";
}
public Person(String name) {
super(name);
this.skillClass=new Mage();
this.dialogue="...";
} etc etc etc
I suppose I could restrict the constructors to limit the repetition but I'm mostly just wondering if there's good best practice that I'm missing here.
Any and all suggestions welcome and if anyone has any good resources to recommend that go deeper than the usual
Class B extends Class A
examples I'd massively appreciate.
In situations like this one when you need to use multiple constructors with different parameters, it is recommended to use the builder pattern like this :
abstract class Creature {
// Fields
private String name;
private int lifeForce;
private int strength;
private int agility;
private Creature(Builder<?> builder) {
this.name = builder.name;
this.lifeForce = builder.lifeForce;
// Add the other attributes here.
}
public static abstract Builder extends Builder<T extends Builder<T>> {
private String name;
private int lifeForce;
private int strength;
private int agility;
public Builder(//here you put the attributes that you need to have in all instances) {
// here you do the affectations.
}
// now you need to make the functions that set each property :
public Builder lifeForce(int lifeForce) {
this.lifeForce = lifeForce;
return this;
}
// you do the same thing for all the other attributes.
...
public Creature build() {
return new Creature(this);
}
}
}
So for the explanation : This pattern will allow you to create instances of your class by setting only the needed attributes.
As here you have subclasses the builder pattern will be little bit more harder to understand but it is the perfect solution in such situation.
We need to apply the builder pattern also for every subclasse so let's do it for the person class :
public class Person extends Creature {
private int anotherField;
public Person(Builder builder) {
super(builder);
this.anotherField = anotherField;
}
public static Builder extends Creature.Builder<Builder> {
public Builder(//add the fieldHere if it is needed in all class instances) {
// if the field is not mandatory you can omit this constructor but you need to put the function below.
}
public Builder anotherField(int anotherField) {
this.anotherField = anotherField;
}
public Person build() {
return new Person(this);
}
}
Now let me show you how tricky is this solution :
1/ declare person with 2 fields :
Person p1 = Person.Builder().name("name").anotherField(0).build();
2/ declare another one with just one field
Person p2 = Person.Builder().agility(1000).build();
Remark : In these two examples, i supposed that your builders' constructors don't have parameters. If for example the name is mandatory field :
Person p3 = Person.Builder("name").anotherField(0).build();
I wish that you had the idea about using builder pattern.

How to enable enum inheritance

I'm writing a library, which has a predefined set of values for an enum.
Let say, my enum looks as below.
public enum EnumClass {
FIRST("first"),
SECOND("second"),
THIRD("third");
private String httpMethodType;
}
Now the client, who is using this library may need to add few more values. Let say, the client needs to add CUSTOM_FIRST and CUSTOM_SECOND. This is not overwriting any existing values, but makes the enum having 5 values.
After this, I should be able to use something like <? extends EnumClass> to have 5 constant possibilities.
What would be the best approach to achieve this?
You cannot have an enum extend another enum, and you cannot "add" values to an existing enum through inheritance.
However, enums can implement interfaces.
What I would do is have the original enum implement a marker interface (i.e. no method declarations), then your client could create their own enum implementing the same interface.
Then your enum values would be referred to by their common interface.
In order to strenghten the requirements, you could have your interface declare relevant methods, e.g. in your case, something in the lines of public String getHTTPMethodType();.
That would force implementing enums to provide an implementation for that method.
This setting coupled with adequate API documentation should help adding functionality in a relatively controlled way.
Self-contained example (don't mind the lazy names here)
package test;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<HTTPMethodConvertible> blah = new ArrayList<>();
blah.add(LibraryEnum.FIRST);
blah.add(ClientEnum.BLABLABLA);
for (HTTPMethodConvertible element: blah) {
System.out.println(element.getHTTPMethodType());
}
}
static interface HTTPMethodConvertible {
public String getHTTPMethodType();
}
static enum LibraryEnum implements HTTPMethodConvertible {
FIRST("first"),
SECOND("second"),
THIRD("third");
String httpMethodType;
LibraryEnum(String s) {
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
static enum ClientEnum implements HTTPMethodConvertible {
FOO("GET"),BAR("PUT"),BLAH("OPTIONS"),MEH("DELETE"),BLABLABLA("POST");
String httpMethodType;
ClientEnum(String s){
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
}
Output
first
POST
Enums are not extensible. To solve your problem simply
turn the enum in a class
create constants for the predefined types
if you want a replacement for Enum.valueOf: track all instances of the class in a static map
For example:
public class MyType {
private static final HashMap<String,MyType> map = new HashMap<>();
private String name;
private String httpMethodType;
// replacement for Enum.valueOf
public static MyType valueOf(String name) {
return map.get(name);
}
public MyType(String name, String httpMethodType) {
this.name = name;
this.httpMethodType = httpMethodType;
map.put(name, this);
}
// accessors
public String name() { return name; }
public String httpMethodType() { return httpMethodType; }
// predefined constants
public static final MyType FIRST = new MyType("FIRST", "first");
public static final MyType SECOND = new MyType("SECOND", "second");
...
}
Think about Enum like a final class with static final instances of itself. Of course you cannot extend final class, but you can use non-final class with static final instances in your library. You can see example of this kind of definition in JDK. Class java.util.logging.Level can be extended with class containing additional set of logging levels.
If you accept this way of implementation, your library code example can be like:
public class EnumClass {
public static final EnumClass FIRST = new EnumClass("first");
public static final EnumClass SECOND = new EnumClass("second");
public static final EnumClass THIRD = new EnumClass("third");
private String httpMethodType;
protected EnumClass(String name){
this.httpMethodType = name;
}
}
Client application can extend list of static members with inheritance:
public final class ClientEnum extends EnumClass{
public static final ClientEnum CUSTOM_FIRST = new ClientEnum("custom_first");
public static final ClientEnum CUSTOM_SECOND = new ClientEnum("custom_second");
private ClientEnum(String name){
super(name);
}
}
I think that this solution is close to what you have asked, because all static instances are visible from client class, and all of them will satisfy your generic wildcard.
We Fixed enum inheritance issue this way, hope it helps
Our App has few classes and each has few child views(nested views), in order to be able to navigate between childViews and save the currentChildview we saved them as enum inside each Class.
but we had to copy paste, some common functionality like next, previous and etc inside each enum.
To avoid that we needed a BaseEnum, we used interface as our base enum:
public interface IBaseEnum {
IBaseEnum[] getList();
int getIndex();
class Utils{
public IBaseEnum next(IBaseEnum enumItem, boolean isCycling){
int index = enumItem.getIndex();
IBaseEnum[] list = enumItem.getList();
if (index + 1 < list.length) {
return list[index + 1];
} else if(isCycling)
return list[0];
else
return null;
}
public IBaseEnum previous(IBaseEnum enumItem, boolean isCycling) {
int index = enumItem.getIndex();
IBaseEnum[] list = enumItem.getList();
IBaseEnum previous;
if (index - 1 >= 0) {
previous = list[index - 1];
}
else {
if (isCycling)
previous = list[list.length - 1];
else
previous = null;
}
return previous;
}
}
}
and this is how we used it
enum ColorEnum implements IBaseEnum {
RED,
YELLOW,
BLUE;
#Override
public IBaseEnum[] getList() {
return values();
}
#Override
public int getIndex() {
return ordinal();
}
public ColorEnum getNext(){
return (ColorEnum) new Utils().next(this,false);
}
public ColorEnum getPrevious(){
return (ColorEnum) new Utils().previous(this,false);
}
}
you could add getNext /getPrevious to the interface too
#wero's answer is very good but has some problems:
the new MyType("FIRST", "first"); will be called before map = new HashMap<>();. in other words, the map will be null when map.add() is called. unfortunately, the occurring error will be NoClassDefFound and it doesn't help to find the problem. check this:
public class Subject {
// predefined constants
public static final Subject FIRST;
public static final Subject SECOND;
private static final HashMap<String, Subject> map;
static {
map = new HashMap<>();
FIRST = new Subject("FIRST");
SECOND = new Subject("SECOND");
}
private final String name;
public Subject(String name) {
this.name = name;
map.put(name, this);
}
// replacement for Enum.valueOf
public static Subject valueOf(String name) {
return map.get(name);
}
// accessors
public String name() {
return name;
}

Java Enum Constructor Undefined

Why am i getting an error "Constructor is undefined" is it in my eclipse IDE?
is there something wrong with my code?
public enum EnumHSClass {
PALADIN ("Paladin"),ROUGE("ROUGE");
}
If you expect your enums to have parameters, you need to declare a constructor and fields for those parameters.
public enum EnumHSClass {
PALADIN ("Paladin"),ROUGE("ROUGE");
private final String name;
private EnumHSClass(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
You need to provide a constructor in your enum like:
public enum EnumHSClass {
PALADIN("Paladin"), ROUGE("ROUGE");
String value;
EnumHSClass(String value) {
this.value = value;
}
}
Note: The constructor for an enum type must be package-private or
private access. It automatically creates the constants that are
defined at the beginning of the enum body. You cannot invoke an enum
constructor yourself.
Ref : http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html
Enums have constructors too, but only with either private or default visibility:
public enum EnumHSClass {
PALADIN ("Paladin"),ROUGE("ROUGE");
private EnumHSClass(String s) {
// do something with s
}
}
You may want to declare a field and create a getter for it, and set the field in the constructor.
Also note that the name of the enum instance is available for free via the (implicit) name() method that all enums have - maybe you can use that instead.
Your code should look like this:
public enum EnumHSClass {
PALADIN ("Paladin"), ROUGE("ROUGE");
private String name;
private EnumHSClass(String name) {
this.name = name;
}
}
public enum Days {
MONDAY(1), TUESDAY(2);
int val;
Days (int val) {
this.val = val;
}
}

Java - Using Accessor and Mutator methods

I am working on a homework assignment. I am confused on how it should be done.
The question is:
Create a class called IDCard that contains a person's name, ID number,
and the name of a file containing the person's photogrpah. Write
accessor and mutator methods for each of these fields. Add the
following two overloaded constructors to the class:
public IDCard() public IDCard(String n, int ID, String filename)
Test your program by creating different ojbects using these two
constructors and printing out their values on the console using the
accessor and mutator methods.
I have re-written this so far:
public class IDCard {
String Name, FileName;
int ID;
public static void main(String[] args) {
}
public IDCard()
{
this.Name = getName();
this.FileName = getFileName();
this.ID = getID();
}
public IDCard(String n, int ID, String filename)
{
}
public String getName()
{
return "Jack Smith";
}
public String getFileName()
{
return "Jack.jpg";
}
public int getID()
{
return 555;
}
}
Let's go over the basics:
"Accessor" and "Mutator" are just fancy names fot a getter and a setter.
A getter, "Accessor", returns a class's variable or its value. A setter, "Mutator", sets a class variable pointer or its value.
So first you need to set up a class with some variables to get/set:
public class IDCard
{
private String mName;
private String mFileName;
private int mID;
}
But oh no! If you instantiate this class the default values for these variables will be meaningless.
B.T.W. "instantiate" is a fancy word for doing:
IDCard test = new IDCard();
So - let's set up a default constructor, this is the method being called when you "instantiate" a class.
public IDCard()
{
mName = "";
mFileName = "";
mID = -1;
}
But what if we do know the values we wanna give our variables? So let's make another constructor, one that takes parameters:
public IDCard(String name, int ID, String filename)
{
mName = name;
mID = ID;
mFileName = filename;
}
Wow - this is nice. But stupid. Because we have no way of accessing (=reading) the values of our variables. So let's add a getter, and while we're at it, add a setter as well:
public String getName()
{
return mName;
}
public void setName( String name )
{
mName = name;
}
Nice. Now we can access mName. Add the rest of the accessors and mutators and you're now a certified Java newbie.
Good luck.
You need to remove the static from your accessor methods - these methods need to be instance methods and access the instance variables
public class IDCard {
public String name, fileName;
public int id;
public IDCard(final String name, final String fileName, final int id) {
this.name = name;
this.fileName = fileName
this.id = id;
}
public String getName() {
return name;
}
}
You can the create an IDCard and use the accessor like this:
final IDCard card = new IDCard();
card.getName();
Each time you call new a new instance of the IDCard will be created and it will have it's own copies of the 3 variables.
If you use the static keyword then those variables are common across every instance of IDCard.
A couple of things to bear in mind:
don't add useless comments - they add code clutter and nothing else.
conform to naming conventions, use lower case of variable names - name not Name.

get() methods in Java enum type

I have an enum type (say for arguments sake CarModel), used throughout an application (numerous classes).
public enum CarModel {
DIABLO,
P911,
DB7;
}
I have various methods that use this CarModel enum type in different ways, and each has a switch statement to set some String variable depending on the enum type, before going on to do other stuff. (e.g. set the Manufacturer of some model, or set the country of origin etc. These results are static at runtime)
The issue is, if I want to add a new model to the enum, I'd need to go to each method, and extend/modify the switch statement to handle its existence. This could easily lead to human error, and/or code duplication (if various methods use the same switch statements).
Rather than using switch statements all-over, I would like to have static methods, that could be edited in a single location, and would allow for behaviour similar to the following:
String country = CarModel.DIABLO.getCountry() // returns Italy
String manufacturer = CarModel.P911.getManufacturer() // returns Porsche
Is this possible with an enum, (and is an enum even the 'correct' way to do this?
You can do something like this.
public enum CarModel {
DIABLO("Lamborghini", "Italy"),
P911("Porsche", "Germany");
private String manufacturer;
private String country;
private CarModel(String manufacturer, String country) {
this.manufacturer = manufacturer;
this.country = country;
}
public String getManufacturer() {
return manufacturer;
}
public String getCountry() {
return country;
}
}
Yes, absolutely. Enums can have their own methods, and those methods can be value-specific. It looks like this:
enum CarModel {
P911 {
public String getManufacturer() { return "Porsche"; }
},
DB7 {
public String getManufacturer() { return "Aston Martin"; }
},
...
public abstract String getManufacturer();
}
You can add more methods, of course.
If you're going to use enums, I would suggest an abstract method declared in the enum, and then a provided implementation for each enum instance.
That way you don't have switch statements everywhere (from which you can easily omit cases) and you have a more reliable and OO-styled polymorphic approach.
abstract public int getEngineSize();
DIABLO {
public int getEngineSize() {
return 6.3; // whatever it really is...
}
}
See here for more examples/discussions etc.
I would suggest adding this information directly into your enum.
Like this:
public enum CarModel {
DIABLO("Lambo"),
P911 ("Porsche");
private String manufacturer;
private CarModel(String manufacturer) {
this.manufacturer = manufacturer;
}
public String getManufacturer() {
return manufacturer;
}
}
and in the class you'd only have to use the getManufacturer method
Moreover enums can implement an interface. You can add some get() methods like getMaxSpeed() or getWeight().
Interface can look like
interface car{
public int getMaxSpeed();
public int getWeight();
}
Yes, this is quite easy to do:
public enum CarModel {
DIABLO("rod"),
P911("jane"),
DB7("freddy");
private String name;
CarModel(String name){
this.name = name;
}
public String getName() {
return name;
}
}
Haha, I recommend you to use "Factory" Design Pattern.
you can make a CarFactory(), to produce new model car.
http://en.wikipedia.org/wiki/Factory_method_pattern

Categories

Resources