I have a situation where I would like to used an instance of an object called Abstraction, which would be a Java interface looking something like:
public interface Abstraction {
public enum Actions {
}
}
The idea being that any class implementing Abstraction has to implement enum Actions (I realise this doesn't work).
A class implementing the interface may look like:
public class AbstractionA implements Abstraction {
public enum Actions {
f, c, r, a
}
}
In another class I would want to create an Abstraction object like:
Abstraction abs = new AbstractionA();
and then be able to access the enum values applicable to the Abstraction object created, e.g.
abs.Action.r;
I realise my approach to this is all wrong but cannot see an appropriate way to handle this type of situation. How can I implement something like this where different implementations of the interface have a varying subset of the options I would generally want to put in an enum?
Perhaps I can implement the enum with all possible options in the interface and then somehow restrict implementations of the interface to using a subset of those enum values?
EDIT:
Another example implementation might be
public class AbstractionB implements Abstraction {
public enum Actions {
f, c, b, r, a
}
}
I think I have figured out a way forward with this:
public interface Abstraction {
public enum Actions {
f, c, b, r, s, a
}
public Actions[] availableActions();
}
Then implement with:
public class HunlAbstractionA implements Abstraction{
#Override
public Actions[] availableActions()
{
Actions[] actions = new Actions[] {Actions.f, Actions.c, Actions.r, Actions.a};
return actions;
}
}
This way I have access to all possible actions listed in the interfaces enum and can make checks to ensure an Action to be dealt with is one of the availableActions for the created class.
Recommendation
I'd recommend the following approach.
This approach uses a combination of generics and reflection to help explicitly indicate the need to implement or choose an appropriate enum, it also gives you the option of preserving information about the enum type whilst hiding all other information about the specific Abstraction implementation.
/**
* An abstraction with an implementation-defined enum
* #param <E> your custom enum.
*/
interface Abstraction<E extends Enum> {
//this gives you the enum constants as a list
Class<E> getEnumType();
}
class AbstractionA implements Abstraction<AbstractionA.EnumA> {
enum EnumA {
FOO,
BAR
}
#Override
public Class<EnumA> getEnumType() {
return EnumA.class;
}
}
class AbstractionB implements Abstraction<AbstractionB.EnumB> {
enum EnumB {
FOO,
BAR
}
#Override
public Class<EnumB> getEnumType() {
return EnumB.class;
}
}
Note that unfortunately we can supply a default implementation of getEnumType() due to type erasure.
Usage Example
class Main {
public static void main(String[] args) {
Abstraction myAbstractionA = new AbstractionA();
Abstraction<AbstractionB.EnumB> myAbstractionB = new AbstractionB();
Class enumAType = myAbstractionA.getEnumType();
Class<AbstractionB.EnumB> enumBType = myAbstractionB.getEnumType();
Object[] enumsA = enumAType.getEnumConstants();
AbstractionB.EnumB[] enumsB = enumBType.getEnumConstants();
System.out.printf("Enums of the same order are still non-identical: %s", enumsA[0].equals(enumsB[0]));
System.out.println();
Enum enumA = ((Enum)enumsA[0]);
Enum enumB = ((Enum)enumsB[1]);
System.out.printf("We can get enum constants in order, and get the orderinal of the enum: A=%s, B=%s", enumA.ordinal(), enumB.ordinal());
System.out.println();
enumA = Enum.valueOf(enumAType, "FOO");
enumB = Enum.valueOf(enumBType, "BAR");
System.out.printf("We can get enum constants by name and get the name out of the enum: A=%s, B=%s", enumA.name(), enumB.name());
System.out.println();
}
}
Alternatives
If you can use an abstract class instead of an interface, you may prefer a solution similar to this related answer.
Edit: If you have a common set of constants you want to share across your actions, you should probably use a global/shared enum for those constants and define only the extensions themselves in the custom Abstractions. If you cast them all to Enum and use .equals() as needed, this should work in most cases.
Background
As you have stated you know, it is not possible to place member objects (variable or classes) of an interface.
However, the good news is that java actually supports the behaviour you want pretty well.
There are 3 key features that relate to my recommendation:
Enums are Objects
Firstly, enums in java are fully-fledged Objects, which all extend java.lang.Enum, and all implement .equals().
So, you can store different any enum class' values in a variable of type java.lang.Enum and compare them with .equals().
And, if you want to pretend that values of different enum classes are the same because they share the same name (or are the nth constant in their respective class), you can do that too.
Note that this also means that custom enums can contain complex data and behaviour like any other class, beyond it's use as a unique identifier.
See the Enum API documentation for details.
Java Reflection
Secondly, Java has extensive reflection support. For our purposes, java.lang.Class has a method called getEnumConstants() for getting the enum constants (or null if the class is not an enum).
See the Class API documentation for details.
Cyclic Dependancies
Thirdly, at least when it comes to generics, Java is permissive when it comes to cyclic dependancies, so you can define a generic interface depends on a specialisation of that generic. Java won't mind.
Interface is a contract that you want anyone to provide an implementation of that contract. In your example code you do not have a method but a definition of a enum called Action.
Generally enum is a set of constants hence we do not expect multiple classes to come up with different implementations of the same constant.
So you might want to rethink about your approach and figure out a better way. Hope this will help moving you in correct direction.
Related
I need to add one optional method in existing abstract class that is extended by more than 50 classes:
public abstract class Animal{...}
This method is not used by all those classes, but in the future it probably will.
The structure of one of my classes is:
public class Dog extends Animal {...}
The cleanest way is using abstract method but it obliges me to change all existing classes.
The workaround is to create "empty" method in abstract class:
public String getString(Map<String, Object> params){
return "";
}
and then override it when I need in classes that extend abstract class.
Is there any better solution?
Having an "empty" method is fine. But in order to be sure, that it will be implemented where it is really needed, consider throwing an exception by default from this method:
throw new UnsupportedOperationException();
A similar approach is used in java.util.AbstractList class:
public E set(int index, E element) {
throw new UnsupportedOperationException();
}
I can't help feeling like you have some architectural/design issues here, but without knowing more, I can't say for sure. If 50 classes are going to inherit from Animal, but not all of them are going to use this method, then I'm wondering if they should really inherit from one common class. Perhaps you need further levels of sub-classing... think Kingdom->Phylum->Sub-Phylum. But my gut says that's still not the right answer for you.
Step back - what are you trying to accomplish? If you're going to implement this function on these classes in the future, then you must also be changing your code to know to use/expect this. The point of inheritance is to allow code to refer to an object's expected common behavior without knowing what type of object it's referencing. In your getString() example, you might have a function as such:
public string SendMessage(Animal someAnimal) {
string message = someAnimal.getString();
// Send the message
}
You can pass it a dog, a cat, a platypus - whatever. The function doesn't care, because it can query the message from its base class.
So when you say you'll have animals that don't implement this message... that implies you'll have logic that ensures only cats and dogs will call this function, and that a platypus is handled differently (or not at all). That kind of defeats the point of inheritance.
A more modern approach would be to use interfaces to establish a "has a" relationship instead of an "is a" relationship. A plane might have an IEngine member, but the specific type of engine can be set at run-time, either by the plane class itself, or by the app if the member is writeable.
public interface IEngine {
string getStatus();
string getMileage();
}
public class Cessna {
public IEngine _engine;
public Cessna() {
_engine = new PropellerEngine();
}
}
You could also inherit directly from that interface... Animals that don't implement IAnimalMessage wouldn't implement that function. Animals that do would be required to. The downside is that each animal will have to have its own implementation, but since your base class currently has an abstract function with no body, I'm assuming that's a non-issue. With this approach, you can determine if the object implements the interface as such:
IAnimalMessage animalMessage = myPlatypus as IAnimalMessage;
// If your playtpus doesn't implement IAnimalMessage,
// animalMessage will be null.
if (null != animalMessage) {
string message = animalMessage.getString();
}
public interface IAnimalMessage {
string getMessage();
}
public class Platypus : IAnimalMessage {
// Add this implementation when Platypus implements IAnimalMessage...
// Not needed before then
public string getMessage() {
return "I'm a cowboy, howdy, howdy, howdy!";
}
}
That's probably the closest to what you're asking for I can suggest... classes that don't need the message won't implement that interface until they do, but the code can easily check if the interface is implemented and act accordingly.
I can offer more helpful/specific thoughts, but I'd need to understand the problem you're trying to solve better.
I have an class with a method which accepts an argument of particular type. The behavior of the method should be dependent on the specific class. For example,
public void doSomething(SomeInterface t) {
...
}
Depending on the actual class of the argument, I need the behavior to change. I need the outer class to perform an action based on the values found in T. Specifically, the outer class needs to construct a Hibernate criteria object which has restrictions which depend on the type of T, which is an implementation of a "Query" interface. The outer class is an implementation of a parameterized builder interface which constructs instances of objects which can be used to execute queries against a data store (for example, Criteria for hibernate, a SearchQueryBuilder for elasticsearch, etc). So as you can see, the problem with having t do the work is that it would require knowledge of HOW to construct these criteria which is beyond its intended purpose of just containing information about WHAT to query
It feels dirty and wrong to do something like
if (t instanceof X) {
...
} else if (t instance of Y) {
...
}
I see a couple problems here.
This requires previous knowledge about the types being passed in
The class is not "closed for modification" and will require a modification every time a new type needs to be supported.
Can someone suggest a good design pattern that can be used to solve this problem? My first thought is to use a factory pattern in combination with strategy and create instances of the class with a "handler" for a specific type. Another thought I had was to create a mapping of Class -> Handler which is supplied to the class at construction time.
Ideas appreciated.
The simplest idea would be to put the logic in the implementations of SomeInterface:
public interface SomeInterface {
public void actOnUsage();
}
public class SomeOtherClass {
public void doSomething(SomeInterface t) {
t.actonUsage();
}
}
Recently, I've discovered this code of the following structure:
Interface:
public interface Base<T> {
public T fromValue(String v);
}
Enum implementation:
public enum AddressType implements Base<AddressType> {
NotSpecified("Not Specified."),
Physical("Physical"),
Postal("Postal");
private final String label;
private AddressType(String label) {
this.label = label;
}
public String getLabel() {
return this.label;
}
#Override
public AddressType fromValue(String v) {
return valueOf(v);
}
}
My immediate reaction is that one cannot create an instance of an enum by deserialization or by reflection, so the fromValue() should be static.
I'm not trying to start a debate, but is this correct? I have read, Why would an Enum implement an interface, and I totally agree with the answers provided, but the above example is invalid.
I am doing this because the "architect" doesn't want to take my answer, so this is to create a strong argument (with facts) why the above approach is good/bad.
Your Base interface does not declare valueOf and the fromValue method is indeed implemented. I see no reason why this code should not compile. If you are referring to the valueOf call inside fromValue, that is a call of a static method defined for every enum. I would have to agree, though, that the design of it is quite misguided as you need an arbitrary member of the enum just to call fromValue and get the real member.
On the other hand, in a project that I'm doing right now I have several enums implementing a common interface. This because the enums are related and I want to be able to treat them uniformly with respect to their common semantics.
In my opinion this design is wrong. In order to use valueFrom() one has to get an instance of this enum beforehand. Thus, it will look like:
AddressType type = AddressType.Postal.valueFrom("Physical");
What sense does it make?
Your Base interface seems to serve a whole other purpose (if any).
It is probably meant to be a String-to-T-converter, since it generates a T from a String. The enum is simply wrong if it implements this interface (#yegor256 already pointed out why). So you can keep the enum and you can have some AddressTypeConverter implements Base<AddressType> which calls AddressType.valueOf() in its fromString() method.
But don't get me wrong: enums implementing interfaces are NOT a bad practice, it's just this particular usage that is completely wrong.
Let's say you have some Java code as follows:
public class Base{
public void m(int x){
// code
}
}
and then a subclass Derived, which extends Base as follows:
public class Derived extends Base{
public void m(int x){ //this is overriding
// code
}
public void m(double x){ //this is overloading
// code
}
}
and then you have some declarations as follows:
Base b = new Base();
Base d = new Derived();
Derived e = new Derived();
b.m(5); //works
d.m(6); //works
d.m(7.0); //does not compile
e.m(8.0); //works
For the one that does not compile, I understand that you are passing in a double into Base's version of the m method, but what I do not understand is... what is the point of ever having a declaration like "Base b = new Derived();" ?
It seems like a good way to run into all kinds of casting problems, and if you want to use a Derived object, why not just go for a declaration like for "e"?
Also, I'm a bit confused as to the meaning of the word "type" as it is used in Java. The way I learned it earlier this summer was, every object has one class, which corresponds to the name of the class following "new" when you instantiate an object, but an object can have as many types as it wants. For example, "e" has type Base, Derived, (and Object ;) ) but its class is Derived. Is this correct?
Also, if Derived implemented an interface called CanDoMath (while still extending Base), is it correct to say that it has type "CanDoMath" as well as Base, Derived, and Object?
I often write functions in the following form:
public Collection<MyObject> foo() {}
public void bar(Collection<MyObject> stuff){}
I could just as easily have made it ArrayList in both instances, however what happens if I later decide to make the representation a Set? The answer is I have a lot of refactoring to do since I changed my method contract. However, if I leave it as Collection I can seamlessly change from ArrayList to HashSet at will. Using the example of ArrayList it has the following types:
Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess
There are a number of cases where confining yourself to a particular (sub)class is not desired, such as the case you have where e.m(8.0);. Suppose, for example, you have a method called move that moves an object in the coordinate graph of a program. However, at the time you write the method you may have both cartesian and radial graphs, handled by different classes.
If you rely on knowing what the sub-class is, you force yourself into a position wherein higher levels of code must know about lower levels of code, when really they just want to rely on the fact that a particular method with a particular signature exists. There are lots of good examples:
Wanting to apply a query to a database while being agnostic to how the connection is made.
Wanting to authenticate a user, without having to know ahead of time the strategy being used.
Wanting to encrypt information, without needing to rip out a bunch of code when a better encryption technique comes along.
In these situations, you simply want to ensure the object has a particular type, which guarantees that particular method signatures are available. In this way your example is contrived; you're asking why not just use a class that has a method wherein a double is the signature's parameter, instead of a class where that isn't available. (Simply put; you can't use a class that doesn't have the available method.)
There is another reason as well. Consider:
class Base {
public void Blah() {
//code
}
}
class Extended extends Base {
private int SuperSensitiveVariable;
public setSuperSensistiveVariable(int value) {
this.SuperSensistiveVariable = value;
}
public void Blah() {
//code
}
}
//elsewhere
Base b = new Extended();
Extended e = new Extended();
Note that in the b case, I do not have access to the method set() and thus can't muck up the super sensitive variable accidentally. I can only do that in the e case. This helps make sure those things are only done in the right place.
Your definition of type is good, as is your understanding of what types a particular object would have.
What is the point of having Base b = new Derived();?
The point of this is using polymorphism to change your implementation. For example, someone might do:
List<String> strings = new LinkedList<String>();
If they do some profiling and find that the most common operation on this list is inefficient for the type of list, they can swap it out for an ArrayList. In this way you get flexibility.
if you want to use a Derived object
If you need the methods on the derived object, then you would use the derived object. Have a look at the BufferedInputStream class - you use this not because of its internal implementation but because it wraps an InputStream and provides convenience methods.
Also, I'm a bit confused as to the meaning of the word "type" as it is used in Java.
It sounds like your teacher is referring to Interfaces and Classes as "types". This is a reasonable abstraction, as a class that implement an interface and extends a class can be referred to in 3 ways, i.e.
public class Foo extends AbstractFoo implements Comparable<Foo>
// Usage
Comparable<Foo> comparable = new Foo();
AbstractFoo abstractFoo = new Foo();
Foo foo = new Foo();
An example of the types being used in different contexts:
new ArrayList<Comparable>().Add(new Foo()); // Foo can be in a collection of Comparable
new ArrayList<AbstractFoo>().Add(new Foo()); // Also in an AbstractFoo collection
This is one of the classic problems on object oriented designs. When something like this happens, it usually means the design can be improved; there is almost always a somewhat elegant solution to these problems....
For example, why dont you pull the m that takes a double up into the base class?
With respect to your second question, an object can have more than one type, because Interfaces are also types, and classes can implement more than one interface.
I have an interface and two objects implementing that interface, massively simplied;
public interface MyInterface {
public int getId();
public int getName();
...
}
public class A implements MyInterface {
...
}
public class B implements MyInterface {
...
}
We are migrating from using one implementation to the other but I need to check that the objects of type B that are generated are equivalent to those of type A. Specifically I mean that for all of the interface methods an object of Type A and Type B will return the same value (I'm just checking my code for generating this objects is correct).
How would you go about this?
Map<String, MyInterface> oldGeneratedObjects = getOldGeneratedObjects();
Map<String, MyInterface> newGeneratedObjects = getNewGeneratedObjects();
// TODO: Establish that for each Key the Values in the two maps return equivalent values.
I'm looking for good coding practices and style here. I appreciate that I could just iterate through one key set pulling out both objects which should be equivalent and then just call all the methods and compare, I'm just thinking there may be a cleaner, more extensible way and I'm interested to learn what options there might be.
Would it be appropriate / possible / advised to override equals or implement Comparable?
Thanks in advance,
Gavin
I would implement a custom version of equals in the test class, not inside any of those implementation classes (since it would clash with the regular equals contract). Something like:
boolean equals(A a, B b) ...
I understand that this check would be required only during the migration period, so the normal equals methods of each implementation should not be affected by this. Namely, A.equals should only return true for an equal instance of A, and should always return false for an instance of B. And vice versa.
Once the migration is over, you no longer need class A neither the tester class, and you can continue using class B without needing to touch its implementation.
Note that if MyInterface (or A and B) extends Comparable, you should also test that the implementations in A and B are equivalent.
(And you surely know that if you implement equals you must also implement hashCode.)