I'm trying to write more generic class for below code so the type and static variables that define in EvenTypes can be changed by the end developer and give them options to add or remove static variables in EventType.
I'm also think of having generic enum for event type as below.
public interface EventType<T extends Enum<T>>
{
String name();
String getFriendlyName();
Class<T> getDeclaringClass();
T getRaw();
public String getFullClassName();
}
Original Code
public class Event implements Serializable
{
private String eventId;
private String eventType;
.....
}
public class EventTypes
{// below static variables can be changed by the developer based on requirements
public static final String DO_FILE_CONVERSION = "100";
public static final String DO_REMOVE_FILE = "101";
public static final String DO_COPY_FILE = "102";
.....
}
public class EventProcessorFactory
{
#SuppressWarnings("rawtypes")
public IEventProcessor createProcessor(EventType eventType)
throws EventException
{
String eventProcessorClassName = (getEvenClassName based on type from properties files);
Class eventProcessorClazz = Class.forName(eventProcessorClassName);
return (IEventProcessor) eventProcessorClazz.newInstance();
}
}
properties.file
----
100=FileConversion.class
101=FileRemove.class
102= FileCopy.class
Make Event an interface and extend it from Serializable.
Then use an enum to implement that Event interface. Example:
public interface Event extends Serializable {
// Throw in your methods here
}
public enum MyEvents implements Event {
DO_FILE_CONVERSION, DO_REMOVE_FILE, DO_COPY_FILE;
// Implement methods
}
This way you have your interface (namely whatever you want Event capable of doing) seperated from the implementation (which Events exist and the implementation of them).
Related
Here is the case.
I have the interface with the field:
public interface SpecificAction extends Action{
String CONSTANT_FIELD = "Specific field";
}
And then I have the parametrized class with the method inside which I want to call my SpecificAction interface field:
public class Test<A extends Action>{
void someMethod(){
System.out.println(A.CONSTANT_FIELD); // there would be the "cannot resolve symbol
// CONSTANT_FIELD" message
}
}
Is there any way how I can call that interface field referring to generic type instead of the interface?
Interfaces define an "is-a" relationship type. They declare methods that should be implemented but not fields or any method-bodies.
What you need to do to get this working is to convert SpecificAction to an abstract class which may have default implemented methods and declare abstract methods (unimplemented).
EDIT: A solution (?)
class Test<A extends Action> {
private final A action;
public Test(A someAction) {
this.action = someAction;
}
void someMethod(){
System.out.println(action.getConstantField());
}
}
class SpecificAction extends Action {
public SpecificAction(String constantField) {
super(constantField);
}
// getConstantField inherited from parent class Action
}
// declaring this class abstract means it cannot be instantiated directly
abstract class Action {
private String constantField = "UNKNOWN";
public Action(String constantField) {
this.constantField = constantField;
}
public String getConstantField() {
return constantField;
}
public void setConstantField(String value) {
this.constantField = value;
}
}
If you call it from somewhere with something like
public static void main(String[] args) {
new Test<SpecificAction>(new SpecificAction("SpecificAction")).someMethod();
}
the output is:
SpecificAction
Process finished with exit code 0
i.e whatever you set the value to. You could refactor it to be constant within SpecificAction (a static final variable that gets passed to the super/parent constructor)
You need to extend your class from interface SpecificAction, not Action. Interface Action does not contains your field.
interface SpecificAction extends Action {
String CONSTANT_FIELD = "Specific field";
}
class Testt<A extends SpecificAction>{
void someMethod(){
System.out.println(A.CONSTANT_FIELD); // Fine
}
}
My sample code structure is like this. There is one parent class Building and one subclass House.
Buiding
public class Building {
private String name;
private int noOfHouses;
}
House
public class House extends Building {
private String houseNumber;
}
I want to write a generic method so that i can access the subclass method also.
something like this.
public <T> void construct(T a){
System.out.println(a.getHouseNumber());
}
Please help.
In fact your example does not show the need of generics. You can use:
public static void construct(House a){
System.out.println(a.getHouseNumber());
}
The same thing, unnecessarily complicated to use generics would also work fine:
public static <T extends House> void construct(T a){
System.out.println(a.getHouseNumber());
}
You can't, and shouldn't do that. It's a bad idea to make parent classes aware of child classes' own concrete methods.
You can use a bounded parameter, if this method is in House, or any other class that doesn't complicate the parent/child relationship:
public static <T extends House> void construct(T a){
System.out.println(a.getHouseNumber());
}
The same thing can be done if the parent is abstract, as suggested above:
public abstract class Building {
private String name;
private int noOfHouses;
public abstract String getHouseNumber();
public static <T extends Building> void construct(T a){
System.out.println(a.getHouseNumber());
}
}
Note that the parent doesn't have to be abstract, as long as it's OK with your design
Generics have nothing to do with this problem. Java provides you with the facility of RunTimePolymorphism, but you can't invoke child's specific method using parent reference.
Consider the following case:
Building b = new House(); //Fine
b.getHouseNumber() // Compiler will be happy only if getHouseNumber is in Building.
I agree with Ernest Kiwele, but if you want to access a method that will be part of a subclass you can override a method in each subclass
abstract class Building{
private String name;
private int noOfHouses;
public abstract String getHouseNumber();
public void construct(){
System.out.println( getHouseNumber() );
}
}
public class House extends Building{
private String houseNumber = "houseNumber";
public String getHouseNumber(){
return this.houseNumber;
}
public static void main(String[] args){
House h = new House();
h.construct();
}
}
Imagining that I have some endpoint defined as:
#Path("path/{variable}/{variable}")
class Resource {
#Path("hey")
public void function(#PathParam("variable") final String variable) {
}
}
In the case of calling path/A/B/hey what will be the value bound to variable?
I'm aware I could use UriInfo#getPathParameters() but I'd like to know what's the specified behaviour in this case.
EDIT: this was obviously a simplification of the problem, the real issue here is when I'm trying to have several resources to inherit from a common behaviour.
Example: imagine that I have nested resources for a family tree (son, father, grandfather) and I want to be able to get the children of a given type.
I'd write:
class AbstractFamilyMember {
#Path("children")
public Collection<Stuff> children(#PathParam("name") final String name) {
return (...);
}
}
#Path(URL)
class Grandfather extends AbstractFamilyMember {
public static final String URL = "something/{name}";
}
#Path(URL)
class Father extends AbstractFamilyMember {
public static final String URL = Grandfather.URL + "father/{name}";
}
#Path(URL)
class Son extends AbstractFamilyMember {
public static final String URL = Father.URL + "son/{name}";
}
Do you have any suggestion to re-design this in order that doesn't involve overriding the children method?
You should use different names for your path parameters variable templates, then you can get the path parameters with UriInfo#getPathParameters() in the AbstractFamilyMember#children() method.
I would avoid the constants for the path. They make it hard to read. Keep it simple:
public abstract class AbstractFamilyMember {
#GET
#Path("children")
public Response children(#Context UriInfo uriInfo) {
MultivaluedMap<String, String> pathParameters = uriInfo.getPathParameters();
String grandfatherName = pathParameters.getFirst("grandfatherName");
String fatherName = pathParameters.getFirst("fatherName");
String sonName = pathParameters.getFirst("sonName");
return Response.ok().build();
}
}
#Path("grandfather/{grandfatherName}")
public class Grandfather extends AbstractFamilyMember {
...
}
#Path("grandfather/{grandfatherName}/father/{fatherName}")
public class Father extends AbstractFamilyMember {
...
}
#Path("grandfather/{grandfatherName}/father/{fatherName}/son/{sonName}")
public class Son extends AbstractFamilyMember {
...
}
Depending on your requirements, you could bind the path parameters to fields:
public abstract class AbstractFamilyMember {
#PathParam("grandfatherName")
private String grandfatherName;
#PathParam("fatherName")
private String fatherName;
#PathParam("sonName")
private String sonName;
...
}
I have five cases of enums that look like this one below:
public enum Answers{
A(0), B(1), C(2), D(3), E(4);
Answers(int code){
this.code = code;
}
protected int code;
public int getCode(){
return this.code;
}
}
They all are all virtually the same except consisting of different "codes" and enumerators. I now have this following class where the generic is an extension of an Enum, however, I need to be able to use the getCode(), which is only in my enums, not a basic enum.
public class test<T extends Enum>{
public void tester(T e){
System.out.println(e.getCode()); //I want to be able to do this,
//however, the basic enum does don't
//have this method, and enums can't extend
//anything.
}
}
Thank you
You can make your enums implement an interface:
public interface Coded {
int getCode();
}
Then:
public enum Answers implements Coded {
...
}
And:
public class Test<T extends Enum & Coded> {
public void tester(T e) {
System.out.println(e.getCode());
}
}
Make all your enums implement a common interface:
public interface HasCode {
int getCode();
}
public enum Answers implements HasCode {
...
}
And then
public class Test<T extends HasCode> {
Have your enum classes implement your own HasCode interface:
public interface HasCode {
public int getCode();
}
public enum Answers implements HasCode {
//...
Then you can restrict T to be a HasCode:
public class test<T extends HasCode>{
and then Java will recognize that anything, even an enum, as long it implements HasCode, will have a getCode() method and it can be called in tester.
If that is the only method you want to add to your Enum then you don't have to do it. Every Enum already has ordinal method which returns value that represents it position in Enum. Take a look at this example
enum Answers{
A,B,C,D,E;
}
class EnumTest<T extends Enum<T>>{
public void tester(T e){
System.out.println(e.ordinal());
}
public static void main(String[] args) throws Exception {
EnumTest<Answers> t = new EnumTest<>();
t.tester(Answers.A);
t.tester(Answers.B);
t.tester(Answers.E);
}
}
Output:
0
1
4
I have a lot of subclasses of an abstract class and each of them declare a public static final field with the same name. I was thinking of having this field in the abstract superclass without initializing it and hoping that each subclass would be forced to initialize it.
I was thinking of this because all of my subclasses of the abstract class declare a public static final String field called UNIQUE_ID, and it is necessary for every subclass to declare such a field with exactly that name.
I hope my question is clear enough, if not please tell me so.
Can something more or less equivalent to this be done?
EDIT: Code added:
My abstract class looks like:
public abstract class ExperimentPanelModel extends Panelizable {
protected String nextButtonText;
protected String backButtonText;
protected String skipButtonText;
protected Properties currentFile;
protected List<Properties> pastFiles = new ArrayList<Properties>();
public ExperimentPanelModel(Properties argcurrentfile, List<Properties> argpastfiles) {
currentFile = argcurrentfile;
pastFiles = argpastfiles;
nextButtonText = "Next";
backButtonText = "Back";
skipButtonText = "Skip";
}
...
}
Some of the non-abstract subclasses of that abstract class look like (note that all of them declare public static final String UNIQUE_ID) :
public class ConfigurationGUI extends ExperimentPanelModel {
public static final String UNIQUE_ID = "ConfigurationGUI";
public static final String DATA_MODIFIED = "DataModified";
Date dateOfLastSession;
int ExperimentalSession;
int ExperimentOrder;
boolean nextButtonEnabled = false;
public ConfigurationGUI(Properties argcurrentfile, List<Properties> argpastfiles) {
super(argcurrentfile, argpastfiles);
nextButtonText = "Confirm";
backButtonText = "Abort";
}
...
}
One example more:
public class Introduction extends ExperimentPanelModel {
public static final String UNIQUE_ID = "Introduction";
public static final String INSTRUCTIONS_XML_FILE = "instructions.xml";
public static final String THIS_INSTRUCTION_PROPERTY = UNIQUE_ID;
private String thisInstructionText = UNIQUE_ID;
Properties readInstructionsProperties = new Properties();
public Introduction(Properties argcurrentfile, List<Properties> argpastfiles) {
...
And the last one:
public class Instruction1 extends ExperimentPanelModel {
public static final String UNIQUE_ID = "Instruction1";
public static final String INSTRUCTIONS_XML_FILE = "instructions.xml";
public static final String THIS_INSTRUCTION_PROPERTY = UNIQUE_ID;
...
}
The field idea won't work, because static fields can't be overridden in subclasses. What you can do is you can declare an abstract method on the abstract class so that your subclasses must implement it.
Also note you can't make it a static method because those don't get overridden either.
In your case I would define the variable in the ancestor. No point in having a variable in each of the extending classes, unless you have a particularly good reason, which you don't sound like having.
+1 for Nathan's reply though. In quite a few cases, that's a better thing to do.
Put the public final field UNIQUE-ID in the abstract class and declare a protected constructor which takes the value for UNIQUE-ID. You'll not be able to make it static though as the values are required to be different for different instances.