I'm writing an abstract class in Java where I'd like a parameter of one of my abstract methods to be an enum, so I've got the following. Note that only subclasses will know what possible states it can have. (Please excuse the contrived example)
public abstract class StateTracker {
public abstract boolean isInState(???????? state);
}
What is ????????? Therein lies the problem:
Ideally it would be an abstract enum called StateEnum that has no instances, and the clients of StateTracker could make their own concrete StateEnums. But we can't do anything like that in Java.
I could make it an interface, but then I'd have no way of ensuring that the subclasses implement it as an enum, which is the goal.
I could change it to Enum < ? >. So I try that, and in my subclass I do something like this:
public class MyStateTracker extends StateTracker {
public enum MyState {
BADSTATE_1, BADSTATE_2
}
#Override
public boolean isInState(?!?!?!?! state) {
// TODO Auto-generated method stub
return false;
}
}
Now what is ?!?!?!?! Here are the possibilities:
MyState. This doesn't compile since it doesn't think that I'm overriding the abstract method.
Enum. Same problem.
How can I ensure that concrete classes use an emum?
It depends on whether you want to be able to ask a StateTracker whether it is in states declared by different enum types.
If you want to lock down the states so that a given state tracker can only be queried for one type of enum, create a generic type:
interface StateTracker<S extends Enum<S>> {
boolean isInState(S state);
}
final class MyStateTracker implements StateTracker<MyStateTracker.MyState> {
enum MyState { S1, S2 };
private MyState state;
...
#Override
public boolean isInState(MyState state) {
return state == this.state;
}
}
If you have a couple of enum types defining states like this:
enum MyState { S1, S2 }
enum YourState { S1, S2 };
… and you want to be able to ask a StateTracker whether it is in any state (defined by any enum, really, unless you also declare a State marker interface for your enum to implement), then create a generic method:
interface StateTracker {
<S extends Enum<S>> boolean isInState(S state);
}
class StateTracker<E extends Enum<E>> {
public abstract boolean isInState(E state);
}
You can use generics to achieve this, Java's enums all extend implicitly java.lang.Enum:
abstract class StateTracker<T extends Enum<?>> {
public abstract boolean isInState(T state);
}
enum MyState {
State_1, State_2
}
class State extends StateTracker<MyState>
{
private MyState currentState = MyState.State_2;
#Override
public boolean isInState(MyState state)
{
return state.equals(currentState);
}
}
public class TestEnum
{
#Test
public void testIsInState()
{
State state = new State();
Assert.assertFalse(state.isInState(MyState.State_1));
Assert.assertTrue(state.isInState(MyState.State_2));
}
}
//This won't compile, so the generic-type must be an Enum
/*
class State2 extends StateTracker<String> //<-- Bound mismatch: The type String is not a valid substitute for the bounded parameter <T extends Enum<?>> of the type StateTracker<T>
{
#Override
public boolean isInState(String state)
{
// TODO Auto-generated method stub
return false;
}
}
*/
Related
I try to write a generic abstract class for my state machine, that will be utilizing enum implementing some interface defined inside that abstract class. I have an abstract class which contains a field implementing a generic interface and some wrapper functions for state switching logic. I try to extend this abstract class and create nested enum type implementing this generic interface, but there are some places, where I have to define explicitely which types I am using for generics. The code below demostrates this problem
public abstract class FiniteStateMachine<C, I> { // <- generic types declared here
private State<C, I> currentState;
protected FiniteStateMachine(State<C, I> initial){ currentState = initial; }
// some other methods for FSM, that I don't want to include in State<>
// ...
public synchronized void process(C context, I input) {
State<C, I> nextState = currentState.process(context, input)
if(currentState != nextState){
currentState.onExit(nextState, context);
State<C, I> previousState = currentState;
currentState = nextState;
nextState.onEnter(previousState, context);
}
}
public interface State<C, I> { //<- this interface should use the same types as FiniteStateMachine
State<C, I> process(C context, I input);
default void onEnter(State<C, I> s, C context) {}
default void onExit(State<C, I> s, C context) {}
}
}
class FSM extends FiniteStateMachine<Data, String> { // <- here I define types used for FSM
public FSM() { super(FSMStage.START); }
enum FSMState implements State<Data, String> { // <- and here I have to repeat them
START{
#Override
public FSMState process(Data p, String s) {
// ...
return NEXT;
},
#Override
public void onExit(State s, Data d) { /* ... */ }
},
NEXT{
// ...
}
}
}
The main concern is that type information is defined in multiple places in extending class - once in type info of the abstract class and onec in interface the enum implements.
FiniteStateMachine is abstract and not an interface because I need some flags and initial state fields (and I can't make an "abstract field" otherwise than with protected constructor hack). FiniteStateMachine.State is an interface, because it's used in enums which cannot be extended. I also want to keep FiniteStateMachine and FiniteStateMachineState in one file, because separate fiels create lots of bloat content in project. Also inside extending FSM the onExit method has a type of State instead of FSMStage.
I tried something like FiniteStateMachine<C, I, State<C, I>> but errors said that 'State is not accessible in the context'.
Is there any way to declare the types in one place in extending class instead of FSM and FSMState like right now? Or maybe there is a way to declare types only for FSMState and make FSM reuse those types? Or maybe this design is completely flawed?
The point is that inner interfaces (and enums too btw) are implicitely static, so they cannot use generic parameters of outer class, because they have no access to instances of the outer class.
So basically this interface is inside the abstract class only for code convenience, you may aswell extract it to separate file. In this design I don't think there is a way to skip multiple generic type declarations.
I think changing the design just to avoid the re-declaration is not worth it - you could make State an abstract class and remove generic types from declaration so it gets generic types from the outer class, but then the idea with enums doesn't work.
C in FiniteStateMachine is not the same C in State class, If you want to make them dependent, you have to define a third type in your FiniteStateMachine which uses C and I with State. You were almost right with FiniteStateMachine<C, I, State<C, I>>, but here how you can do it :
public abstract class FiniteStateMachine<C, I, T extends FiniteStateMachine.State<C, I>> {
private T currentState;
protected FiniteStateMachine(T initial){ currentState = initial; }
public synchronized void process(C context, I input) {
FiniteStateMachine.State<C, I> nextState = currentState.process(context, input);
if(currentState != nextState){
currentState.onExit(nextState, context);
State<C, I> previousState = currentState;
currentState = (T) nextState;
nextState.onEnter(previousState, context);
}
}
public interface State<CTX, INPT> {
State<CTX, INPT> process(CTX context, INPT input);
default void onEnter(State<CTX, INPT> s, CTX context) {}
default void onExit(State<CTX, INPT> s, CTX context) {}
}
}
Now you force the types of State to be same as those defined in FiniteStateMachine.
You can use it now like :
public class FSM extends FiniteStateMachine<Date, String, FSM.FSMState> {
public FSM() { super(FSMState.START); }
public enum FSMState implements FiniteStateMachine.State<Date, String> {
START{
#Override
public FSMState process(Date p, String s) {
// ...
return NEXT;
}
#Override
public void onExit(FiniteStateMachine.State s, Date d) { /* ... */ }
},
NEXT{
#Override
public FiniteStateMachine.State<Date, String> process(Date context, String input) {
return null;
}
// ...
}
}
}
Otherwise, what about repeating the generic types !? From what i've learned so far, there's no way to simplify the writing of your classes. I think the origin of your question was when the two classes are declared in the same file. What if they were separated in two different files ? Do you continue thinking this way ?
How to get Subclass object using implemented interface, if interface is used as Type Parameter for DynamoDBTypeConverter.(e.g. DynamoDBTypeConverter ).
public enum state implements EnumInterface{
CREATED("0");
}
public enum color implements EnumInterface{
GREEN("0");
}
public interface EnumInterface{
void getStatus();
}
public class DynamoDbEnumConverter implements DynamoDBTypeConvereter<String,EnumInterface>{
public EnumInterface unconvert(String value){
// find Object run time, EnumInterface represent color or stat
}
}
Get whether Enum interface represents color or state in unconvert method.
Check this page out: What are Reified Generics? How do they solve Type Erasure problems and why can't they be added without major changes?
Generics are erased in Java.
The only way you're going to get your code to work without hacking around is by providing one instance of the DynamoDbEnumConverter for each EnumInterface:
class DynamoDbEnumConverter<T extends Enum<T> & EnumInterface> implements DynamoDBTypeConvereter<String, T> {
private Class<T> enumType;
public DynamoDbEnumConverter(Class<T> enumType) {
this.enumType = enumType;
}
public EnumInterface unconvert(String value) {
return Enum.valueOf(enumType, value);
}
}
And then:
DynamoDbEnumConverter<Color> colorConverter = new DynamoDbEnumConverter<>(Color.class);
Item is an abstract class with subclasses Potion, Weapon. Shield.
The useItem() method is an abstract method defined in each of Item's subclasses
get_item return object of class Item
The getItem method returns an object of class subclass of Item
case "use":
if (hero.get_item() instanceof Potion) {
hero.<Potion>getItem(Potion.class).useItem();
} else if (hero.get_item() instanceof Weapon) {
hero.<Weapon>getItem(Weapon.class).useItem();
} else if (hero.get_item() instanceof Shield) {
hero.<Shield>getItem(Shield.class).useItem();
}
break;
is there a way I can condense this code into something like...
Class itemclass = hero.getItem().getClass();
hero.<itemclass>getItem(itemclass.class).useItem();
The code above does not compile but I am looking for something like it. I am trying to avoid if else statements because there are many more items.
Edit:
The reason i did not initially use hero.get_item().useItem() was because
i was trying to do
Weapon sword = hero.get_item();
so i could access methods such as sword.getDamage()
However, I would get the error error: incompatible types: Item cannot be converted to a Weapon
so that is why I created (help from #marsouf) hero.<Weapon>getItem(Weapon.class)
Today i created the method abstract public void useItem();
and since it is a method of the Item class I am able to use hero.getItem().useItem()
It would make more sense to haven an Interface for Item with the method useItem().
Then have an implementation for Potion, Shield etc.
This way you avoid having to cast and make it more complex than it is.
useItem() does not belong in the abstract class if its not giving any functionality, and less needed now Interfaces can have default methods.
My idea is to use the magic of generics without not cast
public class Character<T extends Item> {
private T item;
public Character (T item){
this.item = item;
}
public T getItem(){
return item;
}
}
When you create a hero:
Character hero = new Character<Weapon>(new Weapon("sword"));
after this you can use it like:
hero.getItem().useItem(); // abstract method from Item class
hero.getItem().getPower(); //where power is a Weapon method
Character class you can extend like:
public class Hero<T> extend Character<T>{
//add there your custom methods or override Character methods
}
Difficult to answer without seeing the contracts being involved (hero.get_item(), hero.getItem()).
But have you tried:
Class<?> itemClass = hero.get_item().getClass();
hero.getItem(itemClass).useIt();
?
Assuming you are set on using generics the way you're using them... here's how.
First, I've created some extremely simple classes to mimic your structure from this and your other question: a class which uses instances of a particular abstract class.
public class ACOne extends AbstractClass
{
#Override
public void use(){System.out.println("Used item ACOne!");}
}
public class ACTwo extends AbstractClass
{
#Override
public void use(){System.out.println("Used item ACTwo!");}
}
public abstract class AbstractClass
{
public abstract void use();
}
public class UserClass
{
private AbstractClass item;
public UserClass (AbstractClass item)
{
this.item = item;
}
public Class<? extends AbstractClass> getItemClass()
{
return item.getClass();
}
public <T extends AbstractClass> T getItem (Class <? extends T> targetType)
{
return targetType.cast(this.item);
}
public void setItem (AbstractClass item)
{
this.item = item;
}
}
public class CastingSubclasses
{
public void testCastingSubclasses()
{
UserClass user = new UserClass(new ACOne());
user.setItem(new ACTwo());
user.getItem(user.getItemClass()).use();
}
}
This program, when run, prints out "Used item ACTwo!"
The crux here is in the getItemClass method on the UserClass (your Character class).
Also, it's common to call these methods which get the Class object 'getClazz', since there is a default method 'getClass' that you don't want to override.
Here it made sense to just keep the spelling.
I have problem with comparing java generic type if it is type of Void or not. In other words I'm trying to ensure if my generic type T is Void or not.
My sample implementation:
public abstract class Request<T>{
private T member;
protected void comparing(){
if(T instanceof Void) // this make error "Expression expected"
runAnotherMethod();
//if I type
if(member instanceof Void) //Incovertible types; cannot cast T to java.lang.Void
runAnotherMethod();
}
protected void runAnotherMethod(){...}
}
public class ParticularRequest extends Request<Void>{
}
I've tried to compare id via instanceof, Class<T> and Class<Void>, T.class and Void.class.
But the AndroidStudio show me error in every tried case :(
can you help me how to compare it?
thanks.
When using java generics you often need to ask for the class of the generic type in the constructor so that you can actually work with the class. I guess, that is a confusing sentence so just see the example below:
public abstract class Request<T> {
private Class<T> clazz;
// constructor that asks for the class of the generic type
public Request(Class<T> clazz) {
this.clazz = clazz;
}
// helper function involving the class of the generic type.
// in this case we check if the generic type is of class java.lang.Void
protected boolean isVoidRequest(){
return clazz.equals(Void.class);
}
// functionality that depends on the generic type
protected void comparing() {
if (isVoidRequest()) {
runAnotherMethod();
}
}
// ...
}
When you subclass you must pass the class of the generic type to the super constructor.
public class LongRequest extends Request<Long> {
public LongRequest() {
super(Long.class);
}
}
public class VoidRequest extends Request<Void> {
public VoidRequest() {
super(Void.class);
}
}
You can store a private member that is of the generic type of the class.
public abstract class Request<T> {
private T memberOfGenericType;
protected void comparing() {
if (memberOfGenericType instanceof Sometype)
runAnotherMethod();
}
protected void runAnotherMethod() { ... }
public T getMemberOfGenericType() {
return memberOfGenericType;
}
public void setMemberOfGenericType(T value) {
this.memberOfGenericType = value;
}
}
This way, at Runtime, the memberOfGenericType will have the type of Sometype and you will be able to compile the if statement. You can also verify that the memberOfGenericType is Sometype at Runtime, by using the getter I've added.
Anyhow, as a side note, I would say that there's no need of generic type, if you don't use it as a type for a member, method or method parameter and then you should re-consider your design. Also, in particular, the type Void is not instantiable, so you wouldn't be able to pass a valid instance for the class member, which more or less makes the if statement useless.
You can't use T like that. You need some instance to compare. For example some member or parameter:
public abstract class Request<T> {
T member;
protected void comparing(T param){
if(member instanceof Void)
runAnotherMethod();
if(param instanceof Void)
runAnotherMethod();
}
protected void runAnotherMethod(){...}
}
A better approach to accessing the parameter class, used by Guice, is to use the fact that, while a generic class cannot access its own 'class' arguments, its subclasses do have access to these arguments: see https://stackoverflow.com/a/18610693/15472
If you need this, either use Guice' TypeLiterals, or reimplment their logic.
Since there are no objects that are instances of the Void type in Java you can't use instanceof here.
null is the only value that is a member of the type Void. So maybe what you want to do is this?:
if (memberOfGenericType == null)
runAnotherMethod();
About the type Void
No objects of type Void can be created because the class only has a private constructor and it is never invoked from within the class. Void is usually used in these situations:
To get a Class object that represents the return type of methods declared to return void.
As a placeholder type argument, when the fields and variables of that type are not meant to be used.
At run-time T is compiled as Object, and the actual class is unknown. As others said, you should maintain an instance of your parametrized type, but this is not automatic: You need to instantiate it, and the constructor T() cannot be used.
Also java.lang.Void cannot be instantiated, so you should use another class, like a self-made Void class.
Try something like this:
public final class Void {}; // cannot use java.lang.Void, so create another class...
public abstract class Request<T> {
protected abstract T member(); // A member would need to be initialized...
protected void comparing(T param){
if(member() instanceof Void) // Use our Void not java.lang.Void
runAnotherMethod();
}
protected void runAnotherMethod(){...}
}
public class ParticularRequest extends Request<Void>{
#Override
protected Void member() { return new Void(); } // Could be optimized...
}
Edit:
I do not see, why would you need this, however.
If you have different children for different types, then you also could have different implementations, too.
Something like this (types and methods are for example only):
public abstract class Request<T> {
protected abstract T method();
}
public class RequestInt extends Request<Integer> {
#Override
protected Integer method() {...}
}
public class RequestText extends Request<String> {
#Override
protected String method() {...}
}
I got a problem with java when i try to override a method,my code is following:
public abstract class CustomAdapter{
public abstract Boolean addItem(Class<? extends Object> aObject);
}
public class RainAdapter extends CustomAdapter {
#Override
public Boolean addItem(ClassOfRain aRainInfo) {
// do something
return true;
}
}
Can I declare the the "Class" to "ClassOfRain"?
If yes,how to do?
Thanks for your reading!
I think you are a bit confused. Are you sure you are not trying to say:
public abstract class CustomAdapter<T extends Object> {
public abstract Boolean addItem(T aObject);
}
public class RainAdapter extends CustomAdapter<Rain> {
#Override
public Boolean addItem(Rain aRainInfo) {
// do something
return true;
}
}
In my interpretation of your class structure, you are trying to make a generic addItem method, so passing around the actual class object is of no use.
That is not possible. A method override means that you put exactly the same method header. Only thing you can change is the name of the given parameter.
Class<Rain.class> would hold the reflection of Rain class. But this will not work, because overridden methods must have the same formal parameters, so you'll have to use Class<? extends Object>.
the method signatures must match when implementing abstract/interface methods and/or overwriting ... you could do something like this tho
public abstract class CustomAdapter{
public abstract Boolean addItem( Object o );
}
public class RainAdapter extends CustomAdapter {
public Boolean addItem( Object o ){
if ( o.getClassName().equals( "ClassOfRain" ) ){
return this.addItem( (ClassOfRain) o );
}
return false;
}
private Boolean addItem(ClassOfRain aRainInfo) {
// do something
return true;
}
}