Enums with inherited functionality - java

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.

Related

How to tackle following design concern?

I have a class
public class MyCompleteObject {
private MyEnumA enumA;
private MyObjectB objectB;
}
EDIT (Making it more clear): enumA and objectB are interdependent. MyObjectB has 3 subclasses. And each value of MyEnumA goes with object of only one of the subclass of MyObjectB
Since MyObjectB has 3 subclasses, so objectB can be of 3 types. MyEnumA has a lot of values (~30, since I need only their text values, couldn't think of any other option than enum, correct me if enum should not have these many values).
So, there can be 30x3 = 90 combinations of MyEnumA and MyObjectB but not all of those 90 combinations are valid. That's where I am stuck.
What would be the best way to address this? Couple of options which I can think of are:
1) Whenever an instance of MyCompleteObject gets created, I should check if enumA and objectB are consistent with each other and throw an exception if they are not consistent (Not feeling very comfortable with this approach).
2) Make a lot of subclasses with different combinations of enumA and objectB. Again, doesn't seem a promising solution as a lot of subclasses will be created depending on different combinations enumA and objectB.
Update 1)
Third approach which I can think of after reading various answers is:
3) First make extensible rick enum types as #scottb's answer tells. Then I think I can make 3 different constructors in MyCompleteObject class as:
EnumA, EnumB and EnumC are my enums categorized as per their validity with 3 sublclasses of MyObjectB (#scottb's answer). MyObjectBFirst, MyObjectBSecond and MyObjectBThird are the three subclasses of MyObjectB.
public MyCompleteObject(EnumA enumA, MyObjectBFirst objectB){//}
public MyCompleteObject(EnumB enumB, MyObjectBSecond objectB){//}
public MyCompleteObject(EnumC enumC, MyObjectBThird objectB){//}
This can ensure compile time checking. However, 3 different constructors are there. I also looked into builder pattern but couldn't fit it here. It was oriented towards adding up optional arguments, but here I have conditional arguments and all are required.
Thanks!
This sounds like a good use case for an extensible rich enum type:
public enum EnumA implements MyEnumType {
COMMON_TO_A_1,
:
:
COMMON_TO_A_N;
#Override public void commonMethod1() { ... }
:
}
public enum EnumB implements MyEnumType {
COMMON_TO_B_1,
:
:
COMMON_TO_B_N;
#Override public void commonMethod1() { ... }
:
}
public interface MyEnumType {
void commonMethod1();
:
:
int commonMethodN(String myParam);
}
By using MyEnumType as the type name, you will be able to pass in any of your enum groups and perform common type-safe operations on them. The enum facility in Java is robust and typesafe and is usually superior to roll-your-own enum classes. I recommend using the enum facility when possible.
The downside is that this is not an inheritance pattern, and there is no superset of common enums. Sometimes, this can be emulated in code without too much trouble depending on your needs. For example, you can define another enum that provides the class literal of the "base enum" so that you can always refer to those constants in all the operations you perform, as well as any enum groups you have passed using the interface type.
Another downside is that when you pass an enum constant by the interface type, it loses its identity as a member of Java's enum facility. By this I mean that you won't be able to use things like EnumMap and EnumSet with your interface-typed constants. There are workarounds for this limitation, but they may not always be clean to implement.
Make the EnumA value within your class immutable (no setter), and force the user to provide it in the constructor (or through a factory). This forces a constructed class to always use the same value of EnumA. You can then enforce class types on ObjectB in the constructor or in its setter.
public class MyCompleteObject {
private MyEnumA enumA;
private MyObjectB objectB;
public MyCompleteObject(MyEnumA enumA) { this.enumA = enumA; }
public void setObjectB(MyObjectB objectB) {
if(objectB.getClass() == enumA.getValidClassName()) {
this.objectB = objectB;
} else {
throw new InvallidArgumentException();
}
}
}
If you do decide to go with sub classes, I would suggest a base interface, with three abstract classes implementing it - one for each possible type of ObjectB. You can then extend the specific abstract class for each EnumA value that represents the given ObjectB.
public class MyObjectB {};
//Three sub classes of MyObjectB follows
public class MyObjectBType1 extends MyObjectB {};
public class MyObjectBType2 extends MyObjectB {};
public class MyObjectBType3 extends MyObjectB {};
// enum with constructor parameter that tells
// which enum value is compatible with which subclass of MyObjectB
public enum MyEnum {
A (MyObjectBType1.class),
B (MyObjectBType1.class),
C (MyObjectBType2.class),
D (MyObjectBType3.class),
E (MyObjectBType3.class),
;
private Class<? extends MyObjectB> validClassName;
MyEnum(Class<? extends MyObjectB> cls) {
this.validClassName = cls;
}
public Class<? extends MyObjectB> getValidClassName() {
return validClassName;
}
}
Since you mentioned you wanted compile time check solution. Here is one way I could think of.
I am proposing that you inject a subclass of MyOBjectB into MyEnumA definitions.
Lets assume that MyEnumA can be Animal in real life, and MyObjectB is a type of Animal in real life. So, certain animals will be of certain type and any other combination will be invalid.
public class Test {
enum Animal {
PIGEON(new Flyers()), EAGLE(new Flyers()), //flyers
SNAKE(new Crawlers()), CROCODILE(new Crawlers()), //crawlers
COW(new Walkers()), DOG(new Walkers()); //walkers
private AnimalCharacteristics characteristics;
private Animal(AnimalCharacteristics characteristics) {
this.characteristics = characteristics;
}
public AnimalCharacteristics getCharacteristics() {
return characteristics;
}
}
interface AnimalCharacteristics {
void setWeight(double kgs);
};
public static class Flyers implements AnimalCharacteristics {
#Override
public void setWeight(double kgs) {
// do something
}
}
public static class Crawlers implements AnimalCharacteristics {
#Override
public void setWeight(double kgs) {
// do something
}
}
public static class Walkers implements AnimalCharacteristics {
#Override
public void setWeight(double kgs) {
// do something
}
}
public static void main(String[] args) {
System.out.println(Animal.PIGEON.getCharacteristics() instanceof Flyers); //true
System.out.println(Animal.PIGEON.getCharacteristics() instanceof Crawlers); //false
//Make updates
Animal.PIGEON.getCharacteristics().setWeight(0.75);
Animal.COW.getCharacteristics().setWeight(240.00);
}
}
UPDATE
Updated code below as the OP had left a comment saying a new instance is preferable instead of re-using instances of AnimalCharacteristics
public class Test {
enum Animal {
PIGEON(Flyers.class), EAGLE(Flyers.class), //flyers
SNAKE(Crawlers.class), CROCODILE(Crawlers.class), //crawlers
COW(Walkers.class), DOG(Walkers.class); //walkers
private Class<? extends AnimalCharacteristics> characteristicsClass;
private Animal(Class<? extends AnimalCharacteristics> characteristicsClass) {
this.characteristicsClass = characteristicsClass;
}
public AnimalCharacteristics getCharacteristics() {
try {
System.out.println(" ~~~ Creating new instance of: " +
characteristicsClass.getCanonicalName());
return characteristicsClass.newInstance();
} catch (Exception e) {
System.out.println(" ~~~ Exception while creating instance: "
+ e.getMessage());
return null;
}
}
}
interface AnimalCharacteristics {
AnimalCharacteristics setWeight(double kgs);
};
public static class Flyers implements AnimalCharacteristics {
#Override
public AnimalCharacteristics setWeight(double kgs) {
return this;
}
}
public static class Crawlers implements AnimalCharacteristics {
#Override
public AnimalCharacteristics setWeight(double kgs) {
return this;
}
}
public static class Walkers implements AnimalCharacteristics {
#Override
public AnimalCharacteristics setWeight(double kgs) {
return this;
}
}
public static void main(String[] args) {
AnimalCharacteristics pigeon = Animal.PIGEON.getCharacteristics();
System.out.println("Is pigeon a flyer => "
+ (pigeon instanceof Flyers)); //true
System.out.println("Is pigeon a crawler => "
+ (pigeon instanceof Crawlers)); //false
//Make updates
pigeon.setWeight(0.75);
AnimalCharacteristics cow = Animal.COW.getCharacteristics().setWeight(240.00);
System.out.println("Cow is of type:" + cow.getClass().getCanonicalName());
}
}
The above code if run will produce following output:
~~~ Creating new instance of: Test.Flyers
Is pigeon a flyer => true
Is pigeon a crawler => false
~~~ Creating new instance of: Test.Walkers
Cow is of type:Test.Walkers

Avoid Type Casting During Data Processing

I can't seem to figure out the best approach to tackle the following problem. Let's say there is an abstract base class with several concrete subclasses:
public abstract class AbstractType { /* common properties */ }
public class TypeA { /* properties of type A */ }
public class TypeB { /* properties of type A */ }`
These are domain classes (JPA entities). The properties of the types are (amongst other things) used to validate user data. I'm under the assumption that adding logic to the domain model itself is considered bad practice. Therefore, I want to avoid adding a validate method to the concrete subclasses. Like so:
UserInput userInput = ...;
AbstractType data = ...;
data.validate(userInput);
I don't see an option without having to cast the domain model,
if I want to move the logic to a logic layer. With the limited knowledge I have, I can only come up with following two similar "solutions", using some kind of handler interface.
Keep some explicit reference to the handler in the type
public interface TypeHandler {
public validate(AbstractType data, UserInput userInput);
}
/* TypeAHandler & TypeBHandler implementations */
public enum Type {
TYPE_A(new TypeAHandler()),
TYPE_B(new TypeBHandler());
private TypeHandler handler;
public Handler(TypeHandler handler){
this.handler = handler;
}
public TypeHandler getHandler(){ return handler; }
}
public class TypeA {
private Type type = TYPE_A;
/* ... */
}
The handler would than be called in the following manner:
UserInput userInput = ...;
AbstractType data = ...;
data.getType.getHandler().validate(data, userInput);
The reference to the handler could also be added immediately (without the enum in between) as property to the AbstractType class, but that would mean there is a reference to a class inside the logic layer from the domain model (which kind of defeats the purpose of moving the logic to a logic layer?)
The problem here too is that the validate method inside the TypeXHandler needs to cast the data argument to its subclass first before it can start validating.
Or I could implement some method which has a large if-then structure to get the right subclass, cast it and call the appropriate handler which implements an interface similar to the following.
public interface TypeHandler<T extends AbstractType> {
public validate(T data, UserInput userInput);
}
So in both cases there is casting. In the first case there is no huge if-then structure, but the logic and domain are not separated. In the second case there is a very inflexible if-then structure.
To conclude, here is my question. Should I really avoid implementing the logic directly inside the domain? If so, is there any way to avoid the casting, the if-else structure and/or adding additional properties to the domain model (like the enum in the first "solution").
At the end of the day, you're branching based on the subtype (concrete classes) since the logic to validate user input is based on those specific details contained in the subclasses.
Generics don't really help you much here since generics are based primarily on applying logic that is uniform across different types, operating on universal logic applied to a common interface that all applicable types share. Here your logic and interface varies for each subtype.
So your main choices are an inextensible solution where you're modifying central source code (like a big bunch of ifs/elses, a map, etc) and manually branching based on subtype, or using abstraction/dynamic polymorphism as an extensible solution which doesn't require modifying any central source code and automatically branches based on subtype.
Reflection might also be a possible route if you can afford it (it's a bit expensive at runtime) and provided it can fit to give you that universal logic you can implement centrally.
If you don't want to add this validate method to AbstractType and all of its subtypes, then you can always add another level of abstraction on top which does contain a validate method like ValidatorB which implements the IValidator interface and stores an object of TypeB as a member and applies the logic used to validate user input using TypeB's properties.
I studied design patterns last week and I would like to propose my solution (it works but I'm not sure that is the smartest way to resolve your problem).
The idea of my solution is to use a factory: you give a model (in your case a JPA entity) to the factory and it gives you the correct validator for that model.
At the beginning of the program, you have to tell to the factory which is the validator class for each model class of your program through a register method.
Let's start with the implementation...
AbstractModel.java
public abstract class AbstractModel
{
private final int commonProperty;
protected AbstractModel(int commonProperty)
{
this.commonProperty = commonProperty;
}
public int getCommonProperty() { return commonProperty; };
}
In the AbstractModel we put all the common properties of the models.
ModelA.java
public class ModelA extends AbstractModel
{
private final int specificProperty1;
private final int specificProperty2;
public ModelA(int commonProperty, int specificProperty1, int specificProperty2)
{
super(commonProperty);
this.specificProperty1 = specificProperty1;
this.specificProperty2 = specificProperty2;
}
public int getSpecificProperty1() { return specificProperty1; }
public int getSpecificProperty2() { return specificProperty2; }
}
ModelA has got two specific properties.
ModelB.java
public class ModelB extends AbstractModel
{
private final int specificProperty1;
private final int specificProperty2;
public ModelB(int commonProperty, int specificProperty1, int specificProperty2)
{
super(commonProperty);
this.specificProperty1 = specificProperty1;
this.specificProperty2 = specificProperty2;
}
public int getSpecificProperty1() { return specificProperty1; }
public int getSpecificProperty2() { return specificProperty2; }
}
ModelB has got two specific properties too.
Let's say that an instance a of ModelA is valid iff
a.commonProperties == a.specificProperty1 + a.specificProperty2
and an instance b of ModelB is valid iff
b.commonProperties == b.specificProperty1 * b.specificProperty2
Validator.java
public interface Validator
{
public boolean validate();
}
A really simple interface for the validators.
AbstractValidator.java
public abstract class AbstractValidator implements Validator
{
private final AbstractModel toBeValidated;
protected AbstractValidator(AbstractModel toBeValidated)
{
this.toBeValidated = toBeValidated;
}
protected AbstractModel getModel()
{
return toBeValidated;
}
}
This is the superclass of the concrete validators that wraps the model to be validated.
ValidatorA.java
public class ValidatorA extends AbstractValidator
{
protected ValidatorA(AbstractModel toBeValidated)
{
super(toBeValidated);
}
public boolean validate()
{
ModelA modelA = (ModelA) getModel();
return modelA.getCommonProperty() == modelA.getSpecificProperty1() + modelA.getSpecificProperty2();
}
}
The validator for the instances of ModelA.
ValidatorB
public class ValidatorB extends AbstractValidator
{
protected ValidatorB(AbstractModel toBeValidated)
{
super(toBeValidated);
}
public boolean validate()
{
ModelB modelB = (ModelB) getModel();
return modelB.getCommonProperty() == modelB.getSpecificProperty1() * modelB.getSpecificProperty2();
}
}
And this is the validator for the instances of ModelB.
And finally it comes the factory!
ValidatorFactory.java
public class ValidatorsFactory
{
private static ValidatorsFactory instance;
private final HashMap<Class<? extends AbstractModel>, Class<? extends Validator>> registeredValidators;
private ValidatorsFactory()
{
registeredValidators =
new HashMap<Class<? extends AbstractModel>, Class<? extends Validator>>();
}
public static ValidatorsFactory getInstance()
{
if (instance == null)
instance = new ValidatorsFactory();
return instance;
}
public void registerValidator(
Class<? extends AbstractModel> model,
Class<? extends Validator> modelValidator)
{
registeredValidators.put(model, modelValidator);
}
public Validator createValidator(AbstractModel model)
{
Class<? extends Validator> validatorClass = registeredValidators.get(model.getClass());
Constructor<? extends Validator> validatorConstructor = null;
Validator validator = null;
try
{
validatorConstructor = validatorClass.getDeclaredConstructor(new Class<?>[] { AbstractModel.class });
validator = (Validator) validatorConstructor.newInstance(new Object[] { model });
}
catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
{
System.err.println(e.getMessage());
// handle exception
}
return validator;
}
}
The factory is a singleton with two significant method:
registerValidator to add a new pair (modelClass, validatorClass) in the HashMap.
createValidator to obtain the correct validator for the specified model.
This is how to use this pattern:
public class Main
{
public static void main(String args[])
{
ValidatorsFactory factory = ValidatorsFactory.getInstance();
factory.registerValidator(ModelA.class, ValidatorA.class);
factory.registerValidator(ModelB.class, ValidatorB.class);
ModelA modelA = new ModelA(10, 4, 6);
if (factory.createValidator(modelA).validate())
System.out.println("modelA is valid");
else
System.out.println("modelA is not valid");
ModelB modelB = new ModelB(10, 8, 2);
if (factory.createValidator(modelB).validate())
System.out.println("modelB is valid");
else
System.out.println("modelB is not valid");
}
}
output:
modelA is valid [because 10 = 4 + 6]
modelB is not valid [because 10 != 8 * 2]
Note that the model is completely separeted from the controller and it uses only one cast from AbstractModel to a concrete model.
Hope it helps!

How to specify enum constructor

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
}

enum implementation inside interface - Java

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.

Usage of inner class

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).

Categories