I have a class called GreenhouseControls that has a bunch of
classes built into it such as:
public class ThermostatNight extends Event {
public ThermostatNight(long delayTime) {
super(delayTime);
}
public void action() {
// hardware control code here.
thermostat = "Night";
}
public String toString() {
return "Thermostat on night setting";
}
}
I pull values from a text file to get event names such as "ThermostatNight" and time values such as "2000". To instantiate a new object with those values I built a EventFactory that accepts the values as arguments.
This is the class I have built to create new event objects from text file values:
public class EventFactory{
public static Event createSpecificEvent(String eventName, long delayTime) {
Event event = null;
switch(eventName) {
case "ThermostatNight":
event = new ThermostatNight(delayTime); // Compiler error
break;
case "ThermostatDay":
event = new ThermostatDay(delayTime);
break;
case "LightOn":
event = new LightOn(delayTime);
break;
case "LightOff":
event = new LightOff(delayTime);
break;
...
}
}
Everything was working well when I ran the program until I pulled the EventFactory class out of GreenhouseControls and into it's own independent class. Now I am getting a compile time error that says:
"No enclosing instance of type GreenhouseControls is accessible. Must
qualify the allocation with an enclosing instance of type
GreenhouseControls (e.g. x.new A() where x is an instance of
GreenhouseControls)."
See in-line comment in EventFactory class to see where the error occurs at "new ThermostatNight(delayTime)"
Your classes are currently inner classes, which need to be constructed in the context of instances of the containing class. Your options are:
Specify an instance of the outer class when constructing an instance of the inner class
Declare your nested classes as static classes, at which point they won't be inner classes any more
Move the nested classes out of the containing class, making them top level classes
Personally I'd go for the last option if possible - nested classes can be useful at times, but you should only use them when there's a real benefit. There are various restrictions which can be quite subtle and which are best avoided if possible. Do you have any compelling reason to make these nested classes?
The error means that a non-static inner class ThermostatNight is being instantiated from a static method. You need to make the class static (the most likely solution given your code), make the method non-static, or provide an instance explicitly.
public static /*<<==Add this*/ class ThermostatNight extends Event {
public ThermostatNight(long delayTime) {
super(delayTime);
}
public void action() {
// hardware control code here.
thermostat = "Night";
}
public String toString() {
return "Thermostat on night setting";
}
}
To provide an instance explicitly, use this example:
public static Event createSpecificEvent(GreenhouseControls ctrl, String eventName, long delayTime) {
Event event = null;
switch(eventName) {
case "ThermostatNight":
event = ctrl.new ThermostatNight(delayTime);
...
}
Related
Problem: With the following classes, I am trying to select a base class at runtime depending upon an instance variable of parent class in Java. I believe there should be some fundamental property in OOPS which can help me achieve it which I am just missing.
class Transaction{
int id;
enum transactionType;
}
class ATypeTransaction extends Transaction{
/* bunch of instance variable specific to ATypeTransaction */
}
class BTypeTransaction extends Transaction{
/* bunch of instance variable specific to BTypeTransaction */
}
/* The event can be triggered with any transactionType as declared in the enum TransactionType as each event would be associated with one transaction.*/
class Event{
int eventId;
enum transactionType;
}
Based on the transactionType, I have to prepare Transaction Payload and attributes will be different for different base classes as shown below.
My Approach: I am trying to use something like this (static polymorphism within switch-case) in an attempt to resolve the Transaction instance based on the transactionType.The problem with this approach is I am still not able to get hold of the child class. Rather I am getting parent class which stops me from accessing child class attributes.
public Transaction selectTransaction(TransactionType transactionType){
Transaction transaction;
switch(transactionType) {
case = "AType":
transaction= new ATypeTransaction();
break;
case = "BType":
transaction= new BTypeTransaction();
break;
}
return transaction;
}
Please help me out with this problem and provide a good design to solve this. Thanks in advance.
If you're set on selecting type of returned object using switch and enum type I think this will be the best solution:
public static enum TransactionType {
AType,
BType
}
public static class Transaction {
public static void main(String[] args) {
ATypeTransaction transA = selectTransaction(TransactionType.AType);
BTypeTransaction transB = selectTransaction(TransactionType.BType);
Transaction trans = selectTransaction(TransactionType.AType);
transA.doA();
transB.doB();
((ATypeTransaction)trans).doA();
//The following will cause class cast exception
ATypeTransaction transC = selectTransaction(TransactionType.BType);
((BTypeTransaction)trans).doB();
}
#SuppressWarnings("Unchecked")
public static <T extends Transaction> T selectTransaction(TransactionType transactionType){
switch(transactionType) {
case AType:
return (T) new ATypeTransaction();
break;
case BType:
return (T) new BTypeTransaction();
break;
}
}
}
public static class ATypeTransaction extends Transaction {
public void doA() {}
}
public static class BTypeTransaction extends Transaction {
public void doB() {}
}
Unfortunately, unless you know if the result of selectTransaction method will be a specific superclass of class Transaction (so you can save it to a variable of a correct type) or if you check the type using operator instanceof (in case of variable of class Transaction), you'll risk JVM throwing ClassCastException.
put the business logic to your data:
class Transaction{
int id;
enum transactionType;
public void handleTransaction() {
//common code
}
}
class ATypeTransaction extends Transaction{
/* bunch of instance variable specific to ATypeTransaction */
#Override
public void handleTransaction() {
// access specific attributes
super.handleTransaction();
}
}
i think switch-cases in java only works with byte, short, char, string and enum.
You could use the instance of Operator in an if statement.
But maybe there are some better solutions when it comes to design patters.
For some reason, you want your API to contain a method like Transaction selectTransaction(...).
This assumes that your callers won't care about the concrete implementation of Transaction, but can do everything they want just using methods from the Transaction type, never needing anything specific from ATypeTransaction or BTypeTransaction.
Your question shows that this isn't true, the callers seem to need access to specific elements (methods or even fields) of the individual types.
There are two possible roads:
Abandon the common parent class Transaction, and live with two independent classes ATypeTransaction and BTypeTransaction, or
Find the use cases where the subtypes are handled differently, create an abstraction (abstract method) in the parent class, and implement it individually in the subclasses.
We have a Java class, WebCenterGrid. This class is full of methods to do things in a grid such as finding a row, finding a cell value, sorting a column. We have several classes that use this class. The classes using it all refer to different grids, but the functionality is the same.
The only thing that differs is how to create the grid. Some classes do a search which populates the grid (search also refreshes). Some do an updateList() to update the grid, etc.
I would like to add a method to WebCenterGrid to refresh the grid. The problem is as I said each method has a different name.
I somehow want to pass into WebCenterGrid the name of a method to call to do the refresh. I have done some searches and found something about lambda which I did not really understand.
I haven't used C++ in a while but there was some way to pass a method into those methods. This class is in Java not C++, but is there some sort of understandable equivalent?
public class WebCenterGrid {
....
....
public void refresh(Method meth) {
meth();
}
}
Basically, there are two ways.
One is to use reflection, this means: relying on runtime type information, commonly derived from raw strings. Like saying: I have some object of class X, and I want to invoke the method named "doTheFoo()" on that object.
See here for all the glory details.
A slightly better way is to use the MethodHandle class, instead of the "raw" reflection Method class. See here for handles.
But then: reflection is happening at runtime. Your code compiles fine, but if you get any detail wrong, it blows up at runtime.
Thus I suggest looking into lambdas, based on Function, see here.
Instead of having a Method parameter, accept an Interface, and the implementation will define what will be called.
You can use lambdas here as well if you'll define your interface as Functional Interface.
Example:
public class Main {
public static void main(String[] args) {
act(new Run());
act(new Swim());
// Passing a body of the function you want to execute
act(() -> System.out.println("walking"));
}
public static void act(Action action) {
action.act();
}
}
#FunctionalInterface
interface Action {
void act();
}
class Run implements Action {
#Override
public void act() {
System.out.println("running");
}
}
class Swim implements Action {
#Override
public void act() {
System.out.println("swimming");
}
}
Output:
running
swimming
walking
If you have predefined refresh logic, you can create association resolver based on mapping which will help you to define proper service based on some conditions.
public class Main {
static Map<ActionType, Action> actionResolver = new HashMap<>();
// Static init is just for brevity sake
static {
actionResolver.put(ActionType.RUN, new Run());
actionResolver.put(ActionType.WALK, new Walk());
actionResolver.put(ActionType.SWIM, new Swim());
}
public static void main(String[] args) {
act(ActionType.RUN);
act(ActionType.WALK);
act(ActionType.SWIM);
}
public static void act(ActionType actionType) {
Action action = actionResolver.get(actionType);
if (action == null)
throw new IllegalArgumentException("ActionType was not registered");
action.act();
}
}
enum ActionType {
RUN,
SWIM,
WALK
}
Output is the same as above.
Well, since we can't see any of your code, I'll suggest the following solution, that's based on my personal assumption about how your code works.
Please keep in mind that this method is not so scale-able and pretty inefficient if you have 100 different ways of creating grids.
However, if you have (e.g. 3) types of such ways for example, you can use constants!
See below:
public class WebCenterGrid {
//Declare constants with meaningful names for grid creation (add more as you like)
public static final int DEEP_COPY=1, SEARCH=2, REBUILD=3;
public void makeDeepCopy(){
//implementation goes here..
}
public void searchAndPopulate(){
//implementation goes here..
}
public void rebuildGrid(){
//implementation goes here..
}
public void refresh(int operation) {
switch(operation) {
//based on 'operation', call appropriate method!
case DEEP_COPY: this.makeDeepCopy(); break;
case SEARCH: this.searchAndPopulate(); break;
case REBUILD: this.rebuildGrid(); break;
//you can have a default operation for any parameter that is not
//in the list of our defined constants(i.e. the number 143)
default: simpleRefresh(); break;
}
}
}
So what makes the above solution work?
Basically, when you call refresh(int operation) from one of your other classes, you need to pass an int as a parameter. That integer is one of the constants defined at the very top of the class. According to which constant was passed, the switch case will determine which method to call.
EXAMPLE (Let's say that AwesomeGridCreator is a class that when it calls refresh(), in order to update a grid, it has to do a search and then populate the grid (like you mention in your question).
We name an integer (for simplicity) SEARCH_POPULATE and we give it ANY value we want. For example 286.
We can then use that constant from any other class, because we don't care what its value is (in this case 286, but the functionality it provides when calling refresh().
public class WebCenterGrid {
/*some code here*/
public static final int SEARCH_POPULATE = 286; //integer value doesn't matter
public void refresh(int operation) {
switch(operation) {
case SEARCH_POPULATE: this.searchAndPopulate(); break;
}
/*...some other code here, we don't care..*/
}
Then, at the 'calling' class:
public class AwesomeGridCreator{
//some code here
WebCenterGrid wcg = new WebCenterGrid();
//The parameter that we pass below (2), will make the refresh() method call
//the method that we defined in our switch cases ('searchAndPopulate()').
wcg.refresh(wcg.SEARCH_POPULATE);
}
i have my DTO class that is :
public class EmailResponse {
// Make public to avoid getters and setters
public Email email;
public RequestData reqData;
public EmailResponse() {
super();
}
}
and i want to implement to it this interface:
public interface IAssertionErrorDo {
public void onErrorDo();
}
but i want to do it during execution, i don't want to touch "EmailResponse" because it would not be ok to make it implements that interface due they don't belong to the same layer, i mean, EmailResponse would belong to service layer and IAssertionError would belong to test layer. I am using TestNG.
Do you know how i could do this? Regards
EDIT:
My implementation is this:
EmailResponse emailResponse = emailService.getUserEmail(userId);
And the reason i want to do this "injection" is because i have
public class LoggingAssert
extends Assertion {
private static final Logger LOGGER = LoggerFactory.getLogger(LoggingAssert.class);
private IAssertionErrorDo dataE;
#Override
public void onAssertFailure(IAssert a, AssertionError ex) {
LOGGER.info("[ERROR] " + a.getMessage());
if (this.dataE != null) {
this.dataE.onErrorDo();
}
}
public LoggingAssert setOnErrorDo(IAssertionErrorDo object) {
this.object = object;
return this;
}
}
loggingAssert.setOnErrorDo(emailResponse).assertNotNull(emailResponse.getEmail().getId(),
"Checking created email doesn't exists");
So i want to if assert fails execute method onErrorDo() from emailResponse
You could do
public class MyEmailResponse extends EmailResponse implements IAssertionErrorDo {
...
}
implementation calls in interfaces, you can call more than 1 interface if you want by adding commas to separate them..
to call interface methods you simply just use the method's name.
like this:
public class MyEmailResponse implements IAssertionErrorDo
{
public void onErrorDo() {//define it's behavior}
}
if you extend a class you use:
super.MyMethod()
to call the a method inside the extended class, but if you already have an extended class and want a method from another class you have to create an object for that class first then call it, thus:
MyClass mc = new MyClass();
if it is in a different package then
myPackage.MyClass mc = new myPackage.MyClass();
then you call your method from that class using the object you created, which is in this case mc.. so:
mc.MyMethod();
if you want it to return a variable then you will need to add a return statement in that method with the variable you want it to return.
interfaces are usually used for global an changing environments (dynamics), for example if you developed a program and it needs a driver to connect to databases then you will make an interface and send it to the database developers, and each one will fill the codes in that interface and send it back... this guarantees consistency.
when you implement an interface you have to define every method inside it (even if you leave it empty) and you cannot change the interface's methods names nor add... it is used in other areas as well, i don't think you need to use it in your case.
Can somebody help a novice programmer to understand if his solution is correct?
My question is similar to the the following two:
What's wrong with overridable method calls in constructors?
Factory pattern in C#: How to ensure an object instance can only be created by a factory class?
Problem: I want to have subclasses which will differ only in their initialisation method. However, I also want to prevent instantiating these classes without initialization. In other words, I want to ensure, that some "initialize()" method will always be called after instantiation of a subclass:
public abstract class Data {
protected Parameter dataSource;
Data(parameter1){
this.dataSource = parameter1;
loadData(); // should be called to initialise class fields and ensure correct work of other class methods
}
protected abstract loadData(){
... //uses dataSource
}
}
So I decided to perform initialization on a constructor. It worked (now I know that it's a very bad practice) until I created a subclass where the initialize method used some additional parameters:
public class DataFromSpecificSources extends Data {
private Parameter dataSource2;
public DataFromSpecificSources(parameter1, parameter2){
this.dataSource2 = parameter2; // I can't put it here because the constructor is not called yet
super(parameter1); // this, of course, will not work
}
#Override
private void loadData(){
... // uses both dataSource 1 and 2
// or just dataSource2
}
}
This, of course, is not going to work. And I started searching for a right pattern... After I read the answers on questions posted before, I decided to use the factory and limit visibility of the subclass constructor to the package:
My solution:
// factory ensures that loadData() method will be called
public class MyDataFactory(){
public Data createSubClass(parameter1,parameter2){
Data subClass;
if (parameter2 != null){
subClass = new DataFromSpecificSources(parameter1, parameter2);
subClass.loadData();
} else {
subClass = new AnotherSubClass(parameter1);
subClass.loadData()
}
return subClass;
}
}
public abstract class Data {
protected Parameter dataSource;
Data(parameter1){
this.dataSource = parameter1;
}
// I don't call it in constructor anymore - instead it's controlled within the factory
protected abstract loadData(){
... //uses dataSource
}
}
public class DataFromSpecificSources {
private Parameter dataSource2;
protected DataFromSpecificSources(){}
// now this constructor is only visible within package (only for the factory in the same package)
DataFromSpecificSources(parameter1, parameter2){
super(parameter1); // it does not initialise data anymore
this.dataSource2 = parameter2;
}
#Override
protected void loadData(){
... // uses dataSources 1 and 2
}
}
Now factory ensures that subclasses will be initialized (data will be loaded) and instantiation of subclasses is not allowed in other packages. Other classes have no access to constructor of subclasses and are forced to use factory to get an instance of a subclass.
I just wanted to ask if my solution is correct (logically) and Factory method with subclass constructor visibility limited to the package is right choice here?! Or there is any other more effective pattern solving the problem?!
Using a factory is definitely a step in the right direction. The issue I see is that what happens when you want to add a third class that takes a third parameter. Now your Factory is either going to have to have a second overloaded createSubClass method taking the third parameter, or all your code is going to have to be rewritten to provide the third parameter. Additionally you are forcing anyone using the Factory to specify null for the second parameter even if they only want the single parameter class.... when you get to the class that takes 15 parameters how are you going to remember which parameter is which
The solution to this is to use the Builder pattern instead.
public class MyDataBuilder(){
private parameter1 = null;
private parameter2 = null;
public MyDataBuilder withParameter1(parameter1) {
this.parameter1 = parameter1;
return this;
}
public MyDataBuilder withParameter2(parameter2) {
this.parameter2 = parameter2;
return this;
}
public Data createSubClass(){
Data subClass;
if (parameter2 != null){
subClass = new DataFromSpecificSources(parameter1, parameter2);
} else {
subClass = new AnotherSubClass(parameter1);
}
subClass.loadData();
return subClass;
}
}
Now the code creating the Data instances can work like so:
Data data = new MyDataBuilder().withParameter1(param1).withParameter2(param2).create();
or
Data data = new MyDataBuilder().withParameter1(param1).create();
And that code is future-proofed for when you add parameter3... and you can even have the builder with a non-null default for parameter3 if you so need that.
The next thing you notice is that you now have this nice Builder object that contains all the required parameters... so now you can add getters to the Builder and just pass the Builder as the constructor parameter, e.g.
public class DataFromSpecificSources {
...
DataFromSpecificSources(MyDataBuilder builder){
...
}
...
}
So that you now almost have a standard constructor signature
Now for some Java specific improvements. We can make the builder not need to know about the sub-classes at all!
Using a DI framework we can inject the classes that implement the Data interface / abstract class into the Builder and then just iterate through each class until we find a class that supports the configuration of the Builder instance.
The poor-man's DI framework is the /META-INF/services contract and the ServiceLoader class available since JRE 1.6 (though the core logic has been in Java since 1.2)
Your builder's create method will then look a little something like
public Data create() {
for (DataFactory factory: ServiceLoader.load(DataFactory.class)) {
if (factory.canCreate(this)) {
Data result = factory.newInstance(this);
result.loadData();
return result;
}
}
throw new IllegalStateException("not even the default instance supports this config");
}
Whether you want to go to that extreme is questionable... but since you might come across it at some point in time when looking at other people's code, it is probably a good time to point it out to you now.
Oh, the reason why we have to add a Factory class to be looked up by the ServiceLoader is because ServiceLoader expects to call the default constructor, and we have hidden the default constructor so we use a Factory class to do the work for us and allow us to keep the constructor hidden.
There is nothing preventing the Factory classes from being static inner classes in the Data classes (which gives them great visibility on the class they are creating), e.g.
public class UberData extends Data {
private UberData(MyDataBuilder config) {
...
}
public static class Factory extends DataFactory {
protected Data create(MyDataBuilder config) {
return new UberData(config);
}
protected boolean canCreate(MyDataBuilder config) {
return config.hasFlanges() and config.getWidgetCount() < 7;
}
}
}
As we can then list in META-INF/services/com.mypackage.DataFactory
com.mypackage.UberData.Factory
com.mypackage.DataFromSpecificSources.Factory
com.some.otherpackage.AnotherSubClass.Factory
The best bit about this type of solution is it allows adding additional implementations just by adding those implementations to the classpath at run-time... i.e. very loose coupling
Is it possible to get the class type from inside the static initialization block?
This is a simplified version of what I currently have::
class Person extends SuperClass {
String firstName;
static{
// This function is on the "SuperClass":
// I'd for this function to be able to get "Person.class" without me
// having to explicitly type it in but "this.class" does not work in
// a static context.
doSomeReflectionStuff(Person.class); // IN "SuperClass"
}
}
This is closer to what I am doing, which is to initialize a data structure that holds information about the object and its annotations, etc... Perhaps I am using the wrong pattern?
public abstract SuperClass{
static void doSomeReflectionStuff( Class<?> classType, List<FieldData> fieldDataList ){
Field[] fields = classType.getDeclaredFields();
for( Field field : fields ){
// Initialize fieldDataList
}
}
}
public abstract class Person {
#SomeAnnotation
String firstName;
// Holds information on each of the fields, I used a Map<String, FieldData>
// in my actual implementation to map strings to the field information, but that
// seemed a little wordy for this example
static List<FieldData> fieldDataList = new List<FieldData>();
static{
// Again, it seems dangerous to have to type in the "Person.class"
// (or Address.class, PhoneNumber.class, etc...) every time.
// Ideally, I'd liken to eliminate all this code from the Sub class
// since now I have to copy and paste it into each Sub class.
doSomeReflectionStuff(Person.class, fieldDataList);
}
}
Edit
I picked the accepted answer based on what applied best to my problem, however it seems to me that all three of the current answers have their merits.
No, it's not possible without grabbing the stacktrace (which is imo nastier than your initial approach and for which I would in any way prefer Thread#getStackTrace() above new Exception()).
Rather do that job in a non-static initializer (or the default constructor) of the abstract class where you check the initialized status.
public abstract class SuperClass {
{
if (!isInitialized(getClass())) {
initialize(getClass());
}
}
}
The called methods in turn can be safely static.
yes, I use this often to initialize a static Log variable :
e.g. :
public class Project implements Serializable, Cloneable, Comparable<Project> {
private static final Logger LOG = LoggerFactory.getLogger(Project.class);
...
To get a class at runtime, you could do something along the lines of
public class Test {
public static void main(String[] args) {
try{
throw new Exception();
}
catch(Exception e){
StackTraceElement[] sTrace = e.getStackTrace();
// sTrace[0] will be always there
String className = sTrace[0].getClassName();
System.out.println(className);
}
}
}
Not pretty but will do the job (ripped from http://www.artima.com/forums/flat.jsp?forum=1&thread=155230).
This means you still make a call from the subclass (so is in the stack trace), but you don't need to include the XXX.class as an argument.