At present I have a class called TestEnum. In my main method I can work with firstEnum and secondEnum without needing to specify that firstEnum belongs to GroupA and secondEnum belongs to GroupB - the code in TestEnum sorts this out.
Suppose that either firstEnum or secondEnum could be associated with any of the three SubGrouping enum. I want to be able to make this association from within my main method. It is clear I can't use the same approach as with Grouping since GroupA is allocated to firstEnum from within TestEnum.
public enum TestEnum {
firstEnum (Grouping.GroupA),
secondEnum (Grouping.GroupB);
private Grouping group;
TestEnum(Grouping group) {
this.group = group;
}
public enum Grouping {
GroupA, GroupB;
}
public enum SubGrouping {
SubGroup1, SubGroup2, SubGroup3;
}
}
How do I do this? To be more concrete, it would be good to construct an object such as:
TestEnum enumWithinMainMethod = TestEnum.firstEnum(SubGrouping.SubGroup1)
The desired behaviour of this instance is that it belongs to both SubGroup1 as well as GroupA. Then from such an instance it would be good to have the functionality, for example:
switch(enumWithinMainMethod) {
case firstEnum:
// Do something associated with firstEnum
case secondEnum:
// Do something associated with secondEnum
default:
// ...
}
Double think before going this approach. Enum is aimed to be static, constant and with finite set of values. What you are doing here is making Enum no longer constant (as you are changing/initializing it in runtime).
I believe there are other way to do, for example, review if it is actually required to have the relationship determined in runtime? Can't it be defined in compile-time? You may also having a TestEnum-to-SubGroup map, instead of dynamically construct the content of TestEnum.
Anyway, although it is not preferable, it is technically possible in Java.
Of course you cannot delay the "construction" of enum until your main() logic, but you can have enum constructed as normal, and change the internal state.
// Mind the naming convention
public enum TestEnum {
FIRST_ENUM(Grouping.GROUP_A),
SECOND_ENUM (Grouping.GROUP_B);
private Grouping group;
private SubGrouping subGrouping;
TestEnum(Grouping group) {
this.group = group;
}
public void setSubGrouping(SubGrouping subGrouping) {
this.subGrouping = subGrouping;
}
public enum Grouping {
GROUP_A, GROUP_B
}
public enum SubGrouping {
SUB_GROUP_1, SUB_GROUP_2, SUB_GROUP_3;
}
}
Then in your main(), do something like
TestEnum.FIRST_ENUM.setSubGrouping(TestEnum.SubGrouping.SUB_GROUP_1);
TestEnum.SECOND_ENUM.setSubGrouping(TestEnum.SubGrouping.SUB_GROUP_2);
By doing so, you can define the subgrouping of your enum in your main()
Once again, this is NOT PREFERABLE.
You cannot call enum constructors from outside of an enum. You could use a class to get this behaviour.
How about something like this? (The generics are not required, but it does open up the Groupable class to multiple types of groupings.)
public enum Grouping { GroupA, GroupB; }
public enum SubGrouping { SubGroup1, SubGroup2, SubGroup3; }
public class SubGroupable<G extends Enum<G>,S extends Enum<S>> {
private G mainGroup;
private S subGroup;
public Groupable(G group, S subGroup) {
this.mainGroup = group;
this.subGroup = subGroup;
}
public G getGroup() { return mainGroup; }
public S getSubGroup() { return subGroup; }
}
Usage
SubGroupable<Grouping, SubGrouping> g
= new SubGroupable<>(Grouping.GroupA, SubGrouping.SubGroup2);
switch (g.getGroup()) {
case Grouping.GroupA:
//
break;
case Grouping.GroupB:
//
break;
}
You could also create two final groupings:
public final Grouping FIRST_GROUP = Grouping.GroupA;
public final Grouping SECOND_GROUP = Grouping.GroupB;
This way you can use those constants in your case blocks.
switch (g.getGroup()) {
case FIRST_GROUPING: // etc
}
Related
I have the following Enum constants for real life equipment:
HELMET,
CHESTPIECE,
BOOTS,
SWORD,
MACE,
HAMMER,
SHIELD,
BOW,
CROSSBOW,
STAFF
...;
I have another class called Battle which dictates what equipment can be used in that specific battle. For example:
new Battle(Equipment.HAMMER, Equipment.SHIELD, EQUIPMENT.BOW);
Which means that only Hammers, Shields, or Bows can be used.
Now I expanded on that and have the need for sub categories. For example:
new Battle(Equipment.SHIELD, Equipment.Weapons.values())
Which is equivalent to saying:
new Battle(Equipment.SHIELD, Equipment.SWORD, Equipment.MACE, Equipment.HAMMER, ...) etc
Which also means that new Battle(Equipment.values()) should yield every enum value
Since Enums are final, I tried the following:
public interface Equipment { }
public enum MeleeWeapon implements Equipment
{
SWORD,
MACE,
HAMMER,
STAFF, ...;
}
public enum RangedWeapon implements Equipment
{
BOW, CROSSBOW;
}
...
But with this, I'm unable to say Equipment.Weapon.values() // get all weapons, ranged and melee. There's no sense of inherited relationships between classes, and I also lose everything that is not defined in the interface. It doesn't feel like a good solution here.
I tried making regular classes:
public abstract class Equipment
{
private static Set<Equipment> instances = new HashSet<>();
public static Set<Equipment> values()
{
return instances;
}
public Equipment()
{
instances.add(this);
}
}
public abstract class Weapon extends Equipment
{
private static Set<Weapon> instances = new HashSet<>();
public static Set<Weapon> values()
{
return instances;
}
public Weapon()
{
super() // explicit call
instances.add(this);
}
}
public class MeleeWeapon extends Weapon
{
private static Set<MeleeWeapon> instances = new HashSet<>();
public static final MeleeWeapon SWORD = new MeleeWeapon();
public static final MeleeWeapon MACE = new MeleeWeapon();
...
public static Set<MeleeWeapon> values()
{
return instances;
}
public MeleeWeapon()
{
super() // explicit call
instances.add(this);
}
}
Unfortunately there is a ton of repeated code, heavy on memory, and also public static Set<Weapon> values() causes a compile error because it attempts to override values() in the superclass with a different return type. I was able to solve this with generics (<? extends Weapon>) but it's still an awful solution.
What is the right approach here? I need inheritance with my enum values but I cannot find a way how to do so.
Still keeping the enum usage, it is possible to associate each element of the enumeration with the groups to which it belongs and then return filtered groups of elements in dedicated methods.
We'll need another - smaller - enum which enumerates the properties to filter on, for example:
public enum EquipmentType {
WEAPON, ARMOR, TOOL, CLOTHING;
}
The elements of the enumeration are associated with their respective groups:
public enum Equipment {
HELMET(ARMOR),
CHESTPIECE(ARMOR),
BOOTS(ARMOR, CLOTHING),
SWORD(WEAPON),
MACE(WEAPON),
HAMMER(WEAPON, TOOL),
SHIELD(ARMOR),
BOW(WEAPON),
CROSSBOW(WEAPON),
STAFF(WEAPON);
private final Set<EquipmentType> types;
Equipment(EquipmentType... eqTypes) {
this.types = Arrays.stream(eqTypes)
.collect(Collectors.toSet());
}
// common filtering method
private static List<Equipment> filterByType(EquipmentType type) {
return Arrays.stream(values())
.filter(eq -> eq.types.contains(type))
.collect(Collectors.toList());
}
// dedicated methods for each group of items
public static List<Equipment> getWeapons() {
return filterByType(WEAPON);
}
public static List<Equipment> getArmor() {
return filterByType(ARMOR);
}
}
There is still no inheritance or more evolved typing involved in this approach and I think it would be better to avoid using the enum at all if you want more flexibility.
I have two similar classes, each with a single field of the same type.
class Fruit {
private final String name;
}
class Vegetable {
private final String name;
}
I'd like to implement hashCode() for each. My problem is that in my case, collisions between names are somewhat more possible than with "apple" and "carrot," and they both might be in the same Map/Set. I'm wondering what's the most clear way of implementing hashCode to handle this.
So far, I've considered Objects.hash(this.getClass(), name), Objects.hash(<some int unique to this class>, name). I like the first just because it's a bit more self-documenting and robust than the second, but it's not a pattern I've seen in the wild. I also considered <some prime int unique to this class> * Objects.hashCode(name), but that felt fragile, especially if a new field gets added.
Assuming the 2 classes extend a common parent class, I solved this by adding a second field that would tell the instances of two different classes apart. This may be regarded as just another way of using the class name suggested by David Ehrmann in his question. But in my case using an additional field looks more appropriate than using a class name. So here's my abstract parent class:
public abstract class NationalDish {
public String dishName;
public String country;
#Override
public int hashCode() {
return Objects.hash(country, dishName);
}
#Override
public boolean equals(Object obj) {
if (!(obj instanceof NationalDish)) {
return false;
}
NationalDish other = (NationalDish) obj;
return Objects.equals(dishName, other.dishName)
&& Objects.equals(country, other.country);
}
}
Note how having the fields in the parent class allows to define equals() and hash code() in that same class and keep child classes to the minimum:
public class EnglishDish extends NationalDish {
public EnglishDish(String dishName) {
this.dishName = dishName;
this.country = "England";
}
}
public class AmericanDish extends NationalDish {
public AmericanDish(String dishName) {
this.dishName = dishName;
this.country = "USA";
}
}
Now, with country names (or plant types like in the question) in place we can have same name instances which will look different to Java:
public static void main(String[] args) {
NationalDish englishChips = new EnglishDish("Chips");
NationalDish americanChips = new AmericanDish("Chips");
System.out.println(englishChips.equals(americanChips)); // false
}
Check this example:
public interface IConstants {
public enum Levels {
LOW("30 points"), MEDIUM("50 points")
};
public enum Cars {
PORSCHE("250 km/h"), FORD("180 km/h")
}
}
I'd like to have an interface like this, because I want to access my enums this way:
String level = IConstants.Levels.MEDIUM;
String car = IConstants.Cars.PORSCHE;
The compiler shows this message:
constructor IConstants."enum name" is undefined.
Solved this way :
public class Constants {
public static class Levels {
public static String LOW = "30 points";
public static String MEDIUM = "50 points";
};
//... other classes
}
-useful for me in (my case) to have a "tree" in my constants, every constant starting by keyword Constants then subcategory and then value -> Constants.Levels.LOW.
//critize it if it's very bad practise, i agree all comments
-another maybe good thing that there will be all constants in one class
Like Boris the spider told you in comment declaring constants in interfaces is an anti pattern. However your problem comes from the fact that you are passing a String to any instance of your enum but you are not declaring a constructor for this
public enum Levels {
LOW("30 points"), MEDIUM("50 points")
private final String pts;
private Levels(String pts) {
this.pts = pts;
}
public String getPoints() {
return pts;
}
};
This should work.
You are missing constructors in both enums. A private variable and the constructor is required, e.g.
public enum Levels {
private String name;
public Levels(String name) {
this.name = name;
}
}
Also it is considered bad practice to put inner classes, constants in interfaces.
To add to other answers, it will still not compile after an enum constructor is added, because you are assigning a String variable to a Levels or Cars. Please use:
String level = IConstants.Levels.MEDIUM.methodToAccessString();
String car = IConstants.Cars.PORSCHE.methodToAccessString();
Replacing methodToAccessString() with whatever you call it, of course.
I have a question about putting a Java enum in the interface.
To make it clearer, please see the following code:
public interface Thing{
public enum Number{
one(1), two(2), three(3);
private int value;
private Number(int value) {
this.value = value;
}
public int getValue(){
return value;
}
}
public Number getNumber();
public void method2();
...
}
I know that an interface consists of methods with empty bodies. However, the enum I used here needs a constructor and a method to get an associated value. In this example, the proposed interface will not just consist of methods with empty bodies. Is this implementation allowed?
I am not sure if I should put the enum class inside the interface or the class that implements this interface.
If I put the enum in the class that implements this interface, then the method public Number getNumber() needs to return the type of enum, which would force me to import the enum in the interface.
It's perfectly legal to have an enum declared inside an interface. In your situation the interface is just used as a namespace for the enum and nothing more. The interface is used normally wherever you use it.
Example for the Above Things are listed below :
public interface Currency {
enum CurrencyType {
RUPEE,
DOLLAR,
POUND
}
public void setCurrencyType(Currency.CurrencyType currencyVal);
}
public class Test {
Currency.CurrencyType currencyTypeVal = null;
private void doStuff() {
setCurrencyType(Currency.CurrencyType.RUPEE);
System.out.println("displaying: " + getCurrencyType().toString());
}
public Currency.CurrencyType getCurrencyType() {
return currencyTypeVal;
}
public void setCurrencyType(Currency.CurrencyType currencyTypeValue) {
currencyTypeVal = currencyTypeValue;
}
public static void main(String[] args) {
Test test = new Test();
test.doStuff();
}
}
In short, yes, this is okay.
The interface does not contain any method bodies; instead, it contains what you refer to as "empty bodies" and more commonly known as method signatures.
It does not matter that the enum is inside the interface.
Yes, it is legal. In a "real" situation Number would implement Thing, and Thing would probably have one or more empty methods.
I can understand what inner class is and how to write program. My question is in what situation do programmers really need inner class?
Sometimes there is some functionality which is best represented as an object, but which is only meaningful within the context of another object, which does not necessarily need to be exposed to the outside world, and which can benefit from having access to the parent classes data (so as to not violate encapsulation).
The best example that I can think of is putting a Node class inside of a LinkedList. Nodes are only meaningful to the LinkedList, so they only exist within one. No one outside of the LinkedList cares about nodes or should have access to them.
An inner class allows us to remove that logic and place it into its own class. So from an object-oriented point of view, we've taken functionality out of where it doesn't belong and have put it into its own class.
Please go through this link....
http://www.javaworld.com/javaworld/javaqa/2000-03/02-qa-innerclass.html
Also as you know in Java exists nested classes, which is static inner clasess.
From previous posts becomes clear when we need to use an inner class but I think you also interested in the question "Why we need nested classes (static inner class)".
The answer is simply, there is the same purpose as for the inner class except few things.
1) The nested class (static inner) is required when we whant to exclude some logic that concerns another object but this logic might be used in outworld.
The simpliest examples is a builders or editors of some object. For example we have class Foo
which may have a lot of optional fields, to construct such object we may decide to introduce a builder class which will do this work.
public class Foo {
private int param1;
private int param2;
private int param3;
private Foo(FooBuilder builder) {
this.param1 = builder.param1;
this.param2 = builder.param2;
this.param3 = builder.param3;
}
public int getParam1() {
return param1;
}
public void setParam1(int param1) {
this.param1 = param1;
}
public int getParam2() {
return param2;
}
public void setParam2(int param2) {
this.param2 = param2;
}
public int getParam3() {
return param3;
}
public void setParam3(int param3) {
this.param3 = param3;
}
public static class FooBuilder {
private int param1;
private int param2;
private int param3;
public FooBuilder() {
}
public FooBuilder withParameter1(int param1) {
this.param1 = param1;
return this;
}
public FooBuilder withParameter2(int param2) {
this.param2 = param2;
return this;
}
public FooBuilder withParameter3(int param3) {
this.param3 = param3;
return this;
}
public Foo build() {
return new Foo(this);
}
}
}
This example illustrates at leas one reason why we need such classes
2) The second difference between inner and static inner classes is that the first one always has pointer to the parent class. Actully compiler creates synthetic field member for the non static inner class of the type of it's parent, exectly of this reason we can access private members of the parent class. The static inner clasess doesn't has such generated field member. For instance we has just simple parent class with declared non static inner class:
public class Foo {
public class FooBuilder {
}
}
but in fact if take into account the byte code it looks like:
public class Foo {
public class FooBuilder {
private Foo generatedNameHere;
}
}
if you want you can figure out this throught generated byte code.
One of the use of inner class is :
Inner class helps in multiple-inheritance. Inner class allows you to inherit from more than one non-interface.
//first case; can implement if two classes are interface
interface A { }
interface B { }
class X implements A, B { }
//second case; you can extend only one class. This case inner class can help to inherit other class as well
class D { }
abstract class E { }
class Z extends D {
void method() {
return new E() { }; //Anonymous inner class
}
}
When you want to specify a class that has sence only in context with the bounded one.
For example you write a MathOperations class that can execute four operations. So the operations can be represented as inner enum MathOps.
When the inner class is not used anywhere except the inbounded one.
You use anonymous inner classes to specify only the operation, for exmple if you want to sort a collection, you specify a Comparable class just for one method compare.
Collections.sort(employments, new Comparator<Employment>() {
#Override
public int compare(Employment o1, Employment o2) {
return o1.getStartDate().before(o2.getStartDate()) ? 1 : -1 ;
}
});
With inner classes you can access private members of the enclosing class.
They are useful for interface implementations that are only used by the enclosing class (event handlers in a application).
They are useful for providing fine grained access and creation control over an interface implementation that is retrieved externally (maybe something like an Iterator implementation).