How can i represent an object type with a variable such as a string. For example I have DrawPanel1, DrawPanel2, DrawPanel3, all the way through DrawPanel12.
and in a separate class I have a method to create each one with "DrawPanel1 panel = new DrawPanel1();" but I want to have a method.
public void TestPanel(int panelNum){}
where it so it creates DrawPanel(panelNum), so if 2 is passed in it creates a new DrawPanel2.
I thought of doing this with [ String Panel = ("DrawingPanel"+panelNum); ]
but when I used Panel rather than the name of the object it wouldn't work.
I think I understand what you are asking, and I'm going to provide an answer to your immediate question. What you are attempting sounds a little over-complicated, however. The following may need a bit of tweaking...
public void testPanel(Class<?> clazz) {
Object instance = Class.forName(class.getName());
...
}
At this point, instance won't do you much good. You could also create an interface DrawPanelI with the methods used by your different DrawPanel's and have each of them implement that interface. Then, change Object instance to DrawPanelI instance. Now, you can invoke the common methods through instance.
It is a very time consuming task to have variables DrawPanel1 - DrawPanel12. Instead, it would be much easier to have a list of them.
//Making the list
List<DrawPanel> drawPanels = new ArrayList<DrawPanel>();
//Adding to the list
drawPanels.add(new DrawPanel());
//Retrieving from the list
DrawPanel panel = drawPanels.get(0);//"DrawPanel1"
//Processing the list
for (DrawPanel panel: drawPanels){
panel.doStuff();
}
Assuming there is a DrawPanel interface then it would be possible to use a factory pattern:
public class DrawPanelFactory() {
public DrawPanel create(int whichTypeOfPanel) {
if (whichTypeOfPanel == 1) {
return new DrawPanel1();
}
...
if (whichTypeOfPanel == 12) {
return new DrawPanel12();
}
throw new IllegalArgumentException("Unsupported panel type:" + whichTypeOfPanel);
}
}
That ends up being a lot of if statements, but still easily testable. To avoid the if statements use a static Map<Integer, DrawPanelFactoryDelegate> to associate a specific integer value with a specific factory that knows how to create that specific type of DrawPanel:
public class DrawPanelFactory() {
private static Map<Integer, DrawPanelFactoryDelegate> drawPanelFactories = new ...;
static {
drawPanelFactories.put(1, new DrawPanelFactory1());
...
drawPanelFactories.put(12, new DrawPanelFactory12());
}
public DrawPanel create(int whichTypeOfPanel) {
DrawPanelFactoryDelegate delegateFactory = drawPanelFactories.get(whichTypeOfPanel);
if (delegateFactory != null) {
return delegateFactory .create();
}
throw new IllegalArgumentException("Unsupported panel type:" + whichTypeOfPanel);
}
}
interface DrawPanelFactoryDelegate {
public DrawPanel create();
}
DrawPanel1Factory implements DrawPanelFactoryDelegate {
public DrawPanel create() {
return DrawPanel1();
}
}
...
DrawPanel12Factory implements DrawPanelFactoryDelegate {
public DrawPanel create() {
return DrawPanel12();
}
}
then in use:
DrawPanelFactory drawPanelFactory = new DrawPanelFactory();
DrawPanel aDrawPanel = drawPanelFactory.create(1);
...
DrawPanel yetAnotherDrawPanel = drawPanelFactory.create(12);
Related
Firstly, I believe my question is badly worded but don't really understand how to phrase it.
I have a starting interface that is being implemented by a number of classes. What I want to do is to see if there is a way to create a new object such that I am being passed the generic interface, then based on the method .getClass().getSimpleName(), create a new object based on that string.
Is the only way to create a switch case statement? As the number of implementing classes are too many (about 100 or so).
Reference code:
public interface MyInterface {
public void someMethod();
}
then I would have my implementing classes:
public class MyClass1 implements MyInterface {
public void someMethod() { //statements }
}
public class MyClass2 implements MyInterface {
public void someMethod() { //statements }
}
public class MyClass3 implements MyInterface {
public void someMethod() { //statements }
}
What I want to have in the end is another class which is passed an argument of type MyInterface, get the simple name from that and create a new instance of MyClassX based on that simple name.
public class AnotherClass {
public void someMethod(MyInterface interface) {
if (interface == null) {
System.err.println("Invalid reference!");
System.exit(-1);
} else {
String interfaceName = interface.getClass().getSimpleName();
/**
* This is where my problem is!
*/
MyInterface newInterface = new <interfaceName> // where interfaceName would be MyClass1 or 2 or 3...
}
}
}
Any help is highly appreciated!
You can use reflection for this:
public void someMethod(MyInterface myInterface) {
Class<MyInterface> cl = myInterface.getClass();
MyInteface realImplementationObject = cl.newInstance(); // handle exceptions in try/catch block
}
This is a common problem with many solutions. When I face it, I never use reflection because it is difficult to maintain if it is part of a big project.
Typically this problem comes when you have to build an object based on a user selection. You can try a Decorator pattern for that. So, instead of building a different object for each option. You can build a single object adding functionality depending on a selection. For instance:
// you have
Pizza defaultPizza = new BoringPizza();
// user add some ingredients
Pizza commonPizza = new WithCheese(defaultPizza);
// more interesting pizza
Pizza myFavorite = new WithMushroom(commonPizza);
// and so on ...
// then, when the user checks the ingredients, he will see what he ordered:
pizza.ingredients();
// this should show cheese, mushroom, etc.
under the hood:
class WithMushroom implements Pizza {
private final Pizza decorated;
public WithMushroom(Pizza decorated) {
this.decorated = decorated;
}
#Override
public Lizt<String> ingredients() {
List<String> pizzaIngredients = this.decorated.ingredients();
// add the new ingredient
pizzaIngredients.add("Mushroom");
// return the ingredients with the new one
return pizzaIngredients;
}
}
The point is that you are not creating an object for each option. Instead, you create a single object with the required functionality. And each decorator encapsulates a single functionality.
In my understanding of Java, the most common ways to set the instance variables of a class object are:
foo.setFooStuff(bar); // put a setter method inside the class
foo = modifyFooStuff(foo, bar); // pass & return entire object
Let's say my main() has an object of class bigA, which contains a collection of class littleA objects (which contain instance variables), and another object of class bigB, which contains a collection of class littleB objects (which have different instance variables from littleA). How do I write a method to modify instance variables of one or more littleA and littleB objects at the same time?
(Note: I suspect this is a common question, but I searched and didn't find it. Maybe I'm using the wrong terminology.)
Edit: more concrete example: Let's say I'm making Monopoly. A player has money (in various denominations) and properties (some with houses). She wants to upgrade some properties to hotels. Money has to be added and subtracted, as do houses and hotels. I know how to do this in a pass-by-reference language, but not using pass-by-value, unless I make the entire game state into one huge object and pass it around, which seems like a lot of memory shuffling and basically the same as using global variables, which is bad, right?
If I understand your question correctly, you write a method on the bigA/bigB classes that take the value you want to set and then walk the collection of littleA/B objects setting the instance variables as you go. Like:
// Assuming Foo has a member collection of smallFoo
Foo A = new Foo();
// do stuff that populates the collection of smallFoo in A
A.setSmallFooZipCode("23444");
public void setSmallFooZipCode(String zip_ {
// for thisSmallFoo in smallFoo
thisSmallFoo.setZip(zip);
// end for
)
Objects (including your container objects) should represent something--thinking of them in terms of A/B makes this a little tough.
On top of that, if you are always modifying an attribute in two classes at once I'd suggest that's a pretty bad code smell...
Off the top of my head I can't think of anything I'd model this way, so it's hard to come up with an example. Either A and B should be contained in a parent ab class (and that class should have the attribute), or a and b should be the same interface--in either case these would then go into a single collection in a parent container.
So that said, you should have a method on the parent container object that does the work. In most cases it shouldn't be a method like "setAttribute...", it should be a method like "doAction". In other words, if your container is a "Herd" and it contains a bunch of Elephants, then you would tell the Herd to move to a certain location and let the Herd object send a message to each elephant telling it where to go.
If you think of methods in terms of "Asking an object to do something for you" rather than operating on an object, it helps make some of these decisions much easier.
You would simply encapsulate BigA and BigB in another object:
class BigWrapper {
private BigA bigA;
private BigB bigB;
public void someMethod() {
bigA.someMethod();
bigB.someMethod();
}
}
someMethod() within BigA would modify the LittleA instances. Same for BigB:
class BigB {
private LittleA[] littles;
public void someMethod() {
//do something with the littles
}
}
Of course, this solution doesn't allow you to specify which Little instances to target, as well as doesn't allow you to specify which behavior should be performed (which specific method to invoke via the littles).
If you want that flexibility, use callbacks:
interface Little { }
class LittleA implements Little { }
class LittleB implements Little { }
interface Callback<T extends Little> {
void perform(int currentIndex, T currentLittle);
}
class CallbackHandler<T extends Little> {
private int[] indexes;
private Callback<T> callback;
public CallbackHandler(int[] indexes, Callback<T> callback) {
this.indexes = indexes;
this.callback = callback;
}
public void perform(T[] littles) {
for(int i = 0; i < indexes.length; i++) {
int index = indexes[i];
callback.perform(i, littles[index]);
}
}
}
class BigWrapper {
private BigA bigA;
private BigB bigB;
public BigWrapper(BigA bigA, BigB bigB) {
this.bigA = bigA;
this.bigB = bigB;
}
public void perform(CallbackHandler<LittleA> aCallback, CallbackHandler<LittleB> bCallback) {
bigA.perform(aCallback);
bigB.perform(bCallback);
}
}
class BigA {
private LittleA[] littles;
public BigA(LittleA[] littles) {
this.littles = littles;
}
public void perform(CallbackHandler<LittleA> callback) {
callback.perform(littles);
}
}
class BigB {
private LittleB[] littles;
public BigB(LittleB[] littles) {
this.littles = littles;
}
public void perform(CallbackHandler<LittleB> callback) {
callback.perform(littles);
}
}
The CallbackHandler maps the actual callback to the indexes you want to target.
So you would first create the callback:
Callback<LittleA> aCallback = (currentIndex, currentLittle) -> {
//do what you want to the littles
};
Then pass that to a CallbackHandler, which allows you to specify the indexes you wish to target:
int[] indexes = { 0, 1, 2 };
CallbackHandler<LittleA> aCallbackHandler = new CallbackHandler<>(indexes, aCallback);
BigWrapper exposes a perform(CallbackHandler<LittleA>, CallbackHandler<LittleB>), so you would pass the handlers to that method.
An MCVE would look like:
public static void main(String[] args) {
LittleA[] littleA = {
new LittleA(),
new LittleA(),
new LittleA()
};
LittleB[] littleB = {
new LittleB(),
new LittleB(),
new LittleB()
};
BigA bigA = new BigA(littleA);
BigB bigB = new BigB(littleB);
BigWrapper big = new BigWrapper(bigA, bigB);
Callback<LittleA> aCallback = (index, little) -> {
//...
};
Callback<LittleB> bCallback = (index, little) -> {
//...
};
CallbackHandler aCallbackHandler = new CallbackHandler(new int[] { 2, 3, 4 }, aCallback);
CallbackHandler bCallbackHandler = new CallbackHandler(new int[] { 5, 6, 7 }, bCallback);
big.perform(aCallbackHandler, bCallbackHandler);
}
I am designing a Genetic Algorithms library, and am currently constructing the Genome class. This class includes several methods for creating, mutating, crossing, and evaluating genomes, and will be central to this library. This abstract class has two subclasses StaticGenome and VariableGenome. These classes provide additional functionality for fixed or variable length genomes.
Ultimately, crossing any two genomes should be independent of the Genome Type. That being said, the method singlePointCrossover(Genome parent2) takes in two genomes, and returns a new Genome object, which is a special combination of the two parent genomes. However, because Genome is an abstract class, I cannot instantiate a new Genome object as it's offspring.
How can I return a new object of the same type as the subclass, from the superclass?
Any assistance would be greatly appreciated.
The Genome class:
public abstract class Genome <ElementType> {
private String name;
private List<AbstractGenomeElement<ElementType> > elements;
// Mutation Methods //////////////////////////////////////////////
public AbstractGenomeElement<ElementType> mutateElement(AbstractGenomeElement<Integer> element) {
return this.mutateElementAtIndex(this.getElements().indexOf(element));
}
public AbstractGenomeElement<ElementType> mutateElementAtIndex(int i) {
return this.getElement(i).mutate();
}
// Crossover Methods //////////////////////////////////////////////
public Genome<ElementType> singlePointCrossover(Genome<ElementType> genome2){
return multiPointCrossover(genome2, 1);
}
public Genome<ElementType> twoPointCrossover(Genome<ElementType> genome2){
return multiPointCrossover(genome2, 2);
}
public Genome<ElementType> multiPointCrossover(Genome<ElementType> genome2, int crosses){
List<AbstractGenomeElement<ElementType>> newElements= new ArrayList<AbstractGenomeElement<ElementType>>();
Integer nums[] = new Integer[length-1];
for (int i = 0; i < length-1; i++) { nums[i] = i+1; }
List<Integer> shuffled = Arrays.asList(nums);
Collections.shuffle(shuffled);
shuffled = shuffled.subList(0, crosses);
boolean selectFromParentA = true;
for(int i = 0; i < length; i++){
if(shuffled.contains((Integer)i)){
selectFromParentA = !selectFromParentA;
}
if(selectFromParentA) newElements.add(this.getElement(i));
else newElements.add(genome2.getElement(i));
}
// Code fails at this point. "Can not instantiate the type Genome"
return new Genome<ElementType>(name, newElements);
}
}
The two subclasses:
public class StaticGenome<ElementType> extends Genome<ElementType> {
}
public class VariableGenome<ElementType> extends Genome<ElementType> {
}
And the main method I am using for testing:
public static void main(String [] args){
Genome<IntegerElement> genomeA = new StaticGenome<IntegerElement>("Genome A", 50);
Genome<IntegerElement> genomeB = new StaticGenome<IntegerElement>("Genome B", 50);
Genome<IntegerElement> offspring = genomeB.uniformCrossover(genomeA.elementCrossover(genomeA.multiPointCrossover(genomeB, 3)));
offspring.setName("Offspring");
System.out.println(offspring);
}
You could introduce the following method to the abstract class and implement it in the subclasses.
protected abstract Genome<ElementType> newInstance(String name, List<AbstractGenomeElement<ElementType>> elements);
when subclasses implement this they can return the correct instance. i.e: a new instance of their own kind. In your cross over method you could then call this method instead of doing 'new Genome'
You can return a subclass from an overriden method, it's called co-variant return type
abstract class Genome {
abstract Genome singlePointCrossover(Genome parent2);
}
class StaticGenome extends Genome {
#Override
StaticGenome singlePointCrossover(Genome parent2) {
...
}
}
class VariableGenome extends Genome {
#Override
VariableGenome singlePointCrossover(Genome parent2) {
...
}
}
If I am correct, the question is: given some Genome object (that will be some subclass of the abstract class Genome), how can we instantiate a new instance of that subclass?
Well, I don't know if this is the best way, but it's what I've come up with:
public Genome<ElementType>
multiPointCrossover(Genome<ElementType> genome2, int crosses){
// Snip...
Genome g;
try {
g = genome2.getClass()
.getConstructor(String.class, List.class)
.newInstance();
} catch (Exception e) {
// Can throw quite a few exceptions...
}
return g;
}
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#getConstructor(java.lang.Class...)
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/reflect/Constructor.html#newInstance(java.lang.Object...)
Note: I think Dev Blanked's solution is cleaner and simpler to work with. This is just what I came up with when they posted.
I think you need to introduce one more class in between Genome and Static/VariableGenome classes. I am not an expert of microbiology so cannot recommend a good logical name to it. But if you have a new child class(lets say newGenomeClass) of your Genome and acting as a Parent of your Static/VriablGenome classes then you can have your method like this:
public newGenomeClass singlePointCrossover(newGenomeClass parent1,newGenomeClass parent2).
Hope it helps!
I'm refactoring some code in a project I'm working on and I ran into a large if/else if statement that follows the format:
if (changer instanceof AppleChanger)
{
panel = new ApplePanel();
}
else if (changer instanceof OrangeChanger)
{
panel = new OrangePanel();
}
Now my first impulse was to refactor it using polymorphism to have it appear like
panel = changer.getChangerPanel();
However unfortunately the class package doesn't have access to the panel package.
My next impulse was to create a PanelChooser class with an overloaded method:
PanelChooser.getPanel(changer);
//Overloaded Method
public Panel getPanel(OrangeChanger changer)
{
Panel orangePanel = new OrangePanel();
return orangePanel;
}
public Panel getPanel(AppleChanger changer)
{
Panel applePanel = new ApplePanel();
return applePanel;
}
Is this a good solution or is there a better way to solve this?
The fundamental 'problem' here is that you have parallel class hierarchies. You're not going to be able to replace that if statement without some fairly heavy refactoring. Some suggestions are on c2 wiki.
The best you can do, and possibly a perfectly fine solution, is to move the if statement into a 'factory' class and make sure it's not duplicated anywhere else.
I think its good that your first impulse didn't work :) Otherwise you would couple you changer code (which should be something about logic) to UI code (panel) and its wrong.
Now I can offer you the following solution:
create an interface PanelCreator with method Panel createPanel like this:
interface PanelCreator {
Panel createPanel();
}
Now, provide 2 implementations:
public class OrangePanelCreator implements PanelCreator{
Panel createPanel() {
return new OrangePanel();
}
}
public class ApplePanelCreator implements PanelCreator {
Panel createPanel() {
return new ApplePanel();
}
}
And now come the interesting part:
Create a Map, PanelCreator> this would act like a registry for your panels:
Map<Class<Changer>, PanelCreator> registry = new HashMap<>;
registry.put(OrangeChanger.class, new OrangePanelCreator());
registry.put(AppleChanger.class, new ApplePanelCreator());
And in your code now you can do the following thing:
panel = registry.get(changer.getClass()).createPanel();
I think it will be more elegant since you can easily change implementations of creators given the changer.
Hope this helps
If there is more than one of this if/else constructs in the code dependending on the instance type of a Changer, you can use the visitor pattern like this:
public interface ChangerVisitor {
void visit(OrangeChanger changer);
void visit(AppleChanger changer);
...
}
public class ChangerVisitorEnabler<V extends ChangerVisitor> {
public static <V extends ChangerVisitor> ChangerVisitorEnabler<V> enable(V) {
return new ChangerVisitorEnabler<V>(visitor);
}
private final V visitor;
private ChangerVisitorEnabler(V visitor) {
this.visitor = visitor;
}
public V visit(Charger changer) {
if (changer instanceof OrangeChanger) {
visitor.visit((OrangeChanger)changer);
} else if (changer instanceof AppleChanger) {
visitor.visit((AppleChanger)changer);
} else {
throw new IllegalArgumentException("Unsupported charger type: " + changer);
}
return visitor;
}
}
Now you have a single type check code block and a type safe interface:
public PanelChooser implements ChangerVisitor {
public static Panel choosePanel(Changer changer) {
return ChangerVisitorEnabler.enable(new PanelChooser()).visit(changer).panel;
}
private Panel panel;
private PanelChooser() {
}
void visit(OrangeChanger changer) {
panel = orangePanel();
}
void visit(AppleChanger changer) {
panel = applePanel();
}
}
The usage is very simple:
panel = PanelChooser.choosePanel(chooser);
Perhaps you can do:
public Panel getPanel(Changer changer)
{
String changerClassName = changer.class.getName();
String panelClassName = changerClassName.replaceFirst("Changer", "Panel");
Panel panel = (Panel) Class.forName(panelClassName).newInstance();
return panel;
}
I don't program in Java, but that is what I would try if this were in C#. I also don't know if this would work with your packages.
Good luck!
I don't see enough existing code and design at whole. So probably, first of all I would try to move the code with panel instantiation to the same place where Changer instance is created. Because choosing a Panel is the same decision as choosing a Changer.
If a selected Changer is dynamically selected, you may just create these panels and then show/hide them accordingly.
I'd do the following:
Have an interface PanelChooser with a single method returning a Panel for a Changer.
Have an implementation ClassBasedPanelChooser returning a panel when the Change implements a certain class and null otherwise. The class and the panel to be returned get passed in in the constructor.
Have another implementation CascadingPanelChooser which takes a list of PanelChoosers in the constructor arguments and on call of its method asks each PanelChooser to provide a panel until it receives a not null panel, then it returns that panel.
Your solution will not work, because Java selects the method based on the compiletime type (which here is probably Changer). You could use a Map<Class<? extends Changer>, Panel> (or Map<Class<? extends Changer>, Class<? extens Panel>> if you need to create new instances every time). This solution does require extra work if you need this to work for - yet unknown - subclasses of for example OrangeChanger.
eg for a single instance per Changer subclass
changerToPanel.get(changer.getClass());
or if you need new instances:
changerToPanelClass.get(changer.getClass()).newInstance();
The other option would be to go for your initial hunch, and make Changer know about Panel.
Take a look at the Factory and Abstract Factory Patterns.
The Factory Pattern is a creational pattern as it is used to control class instantiation. The factory pattern is used to replace class constructors, abstracting the process of object generation so that the type of the object instantiated can be determined at run-time.
Abstract Factory Pattern is a creational pattern, as it is used to control class instantiation. The abstract factory pattern is used to provide a client with a set of related or dependent objects. The family of objects created by the factory is determined at run-time according to the selection of concrete factory class.
Do not use instanceof.Why polymorphism fails
The only place to use instanceof is inside equals method.
To answer your question. Follow this link.
Credits to Cowan and jordao .
Using Reflection.
public final class Handler {
public static void handle(Object o) {
for (Method handler : Handler.class.getMethods()) {
if (handler.getName().equals("getPanel") &&
handler.getParameterTypes()[0] == o.getClass()) {
try {
handler.invoke(null, o);
return;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
throw new RuntimeException("Can't handle");
}
public static void handle(Apple num) { /* ... */ }
public static void handle(Orange num) { /* ... */ }
Chain of Responsibility
public abstract class Changer{
private Changer next;
public final boolean handle(Object o) {
boolean handled = doHandle(o);
if (handled) { return true; }
else if (next == null) { return false; }
else { return next.handle(o); }
}
public void setNext(Changer next) { this.next = next; }
protected abstract boolean doHandle(Object o);
}
public class AppleHandler extends Changer{
#Override
protected boolean doHandle(Object o) {
if (!o instanceof Apple ) {
return false;
}
OrangeHandler.handle((Orange) o);
return true;
}
}
When calling a method that adds an object to a collection in GWT I get a null pointer error. I have no idea why as everything I have done creates a very simple object (only contains a string). Here is the code that calls the function and the function:
public class PlantMenu extends VerticalPanel {
private Collection<PlantData> plantList;
private Collection<PlantData> newPlantData;
public PlantMenu() {
createPlants();
/*
for(Iterator<PlantData> i = plantList.iterator(); i.hasNext();) {
Window.alert(i.next().getPlantName());
}*/
}
public Collection<PlantData> createPlants() {
PlantData plant1 = new PlantData("Herbs");
PlantData plant2 = new PlantData("Flowers");
PlantData plant3 = new PlantData("Vegetable");
newPlantData.add(plant1);
newPlantData.add(plant2);
newPlantData.add(plant3);
return newPlantData;
}
}
It errors out (null pointer) when trying to add the first plant, this line:
PlantData plant1 = new PlantData("Herbs");
Any help appreciated :)
You didn't initialize your collections. Despite, you already told that its not on that line, but I doubt it. Showing a full exception stack would be much more helpful though. And the exception may occur in your PlantData constructor, but you didn't show it here.
You could do something like this,
private Collection<PlantData> plantList = new ArrayList<PlantData>();
private Collection<PlantData> newPlantData = new ArrayList<PlantData>();
I have used ArrayList, because generally we use ArrayList. Other implementation can also be used, according to the requirements.
You have not initialised your variables properly, this has nothing to do with GWT and is just basic Java. Here's a working version:
public class PlantMenu extends VerticalPanel {
private List<PlantData> plantList = new ArrayList<PlantData>();
private List<PlantData> newPlantData = new ArrayList<PlantData>();
public PlantMenu() {
createPlants();
for(PlantData plant : newPlantData) {
Window.alert(plant.getPlantName());
}
}
public List<PlantData> createPlants() {
newPlantData.add(new PlantData("Herbs"));
newPlantData.add(new PlantData("Flowers"));
newPlantData.add(new PlantData("Vegetable"));
return newPlantData;
}
}
As a side note, you shouldn't be extending VerticalPanel, but rather extending Composite and then using a vertical panel as your widget using setWidget(...);