Here's the sort of thing I'm trying to do:
class Foo {
private ArrayList<Widget> things; //Contains WidgetA, WidgetB and WidgetAB objects
//...
void process(int wIndex) {
process(things.get(wIndex);
}
private void process(WidgetA w) {
//Do things
}
private void process(WidgetB w) {
//Do other things
}
private void process(WidgetAB w) {
//Do completely different things
}
}
abstract class Widget {
//...
}
class WidgetA extends Widget {
//...
}
class WidgetB extends Widget {
}
class WidgetAB extends WidgetA {
}
Basically, a separate class gets an array index from user input, and passes it to the process(int) method, which is supposed to kick off a type-specific process() method to process the object at the passed index. The problem is that the objects are treated as Widget objects, not WidgetA, etc. I could loop through the types using instanceof, I guess, but I'm trying to avoid using that.
The logic in the process() methods needs to access private fields in the Foo class, so moving them to the Widget subclasses might not be the best idea.
So the question is, is there a way for the correct process() method to be called for a given Widget subtype, without using instanceof?
Yes, have a look at the Visitor pattern - also known as double dispatch.
Another potential solution is to use Java's reflection API's. Example:
class Foo {
private ArrayList<Widget> things; //Contains WidgetA, WidgetB and WidgetAB objects
//...
void process(int wIndex) {
Widget theWidget = things.get(wIndex);
try {
Class type = theWidget.getClass();
Class[] arg_types = new Class[]{type};
this.getMethod("process", arg_types).invoke(this, theWidget);
} catch (Exception e) {
//Could be SecurityException or NoSuchMethodException
}
}
private void process(WidgetA w) {
//Do things
}
private void process(WidgetB w) {
//Do other things
}
private void process(WidgetAB w) {
//Do completely different things
}
}
abstract class Widget {
//...
}
class WidgetA extends Widget {
//...
}
class WidgetB extends Widget {
}
class WidgetAB extends WidgetA {
}
The issue here being that you have to have defined a process() method for each type of object in the things list or an exception will be thrown at run-time. The compiler will not warn you if you are missing an implementation.
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.
Premise
Existing codebase (not likely to change):
public interface Shape {
void print();
}
And with the implementations such as (Circle, Triangle, Square, etc):
public final class Circle implements Shape {
private final CircleInput input;
public Circle(CircleInput input) {
this.input = input;
}
#Override
public void print() { ... }
}
CircleInput, TriangleInput, and SquareInput are NOT related at all (disjoint types).
Problem
Input objects can be very complex and I want users to create a class that encapsulates their own business logic. I explored two approaches, but they were both clunky and that leads me to think if I am approaching the problem incorrectly and there is a better way to use Java.
Option 1
I thought about defining a generic interface:
public interface ShapeInput<T> {
T getInput();
}
User can then create:
public final class MyCircleInput<CircleInput> {
private final ShapeDependency shapeDependency;
#Inject
MyCircleInput(ShapeDependency shapeDependency) {
this.shapeDependency = shapeDependency;
}
#Override
public CircleInput getInput() {
return createCircleInput(shapeDependency);
}
// ... very complex business logic ...
private static CircleInput createCircleInput(
ShapeDependency shapeDependency) {
// returns a CircleInput
}
}
then use a ShapeFactory to create the correct instance based on type. But I am unable to say ShapeInput<CircleInput | TriangleInput> and enforcing this behavior requires runtime checks.
Option 2
I could use inheritance on Shape directly:
public abstract class AbstractShape implements Shape {
protected final Shape shapeImpl;
public AbstractShape(CircleInput input) {
this.shapeImpl = new Circle(input);
}
public AbstractShape(TriangleInput input) {
this.shapeImpl = new Triangle(input);
}
// Proxies print() to the underlying impl.
#Override
public void print() {
return shapeImpl.print();
}
}
and users can create:
public final MyCircle extends AbstractShape {
#Inject
MyCircle(ShapeDependency shapeDependency) {
super(createCircleInput(shapeDependency));
}
// ... very complex business logic ...
private static CircleInput createCircleInput(
ShapeDependency shapeDependency) {
// returns a CircleInput
}
}
So Circle, Square, Triangle (which are all Shapes) and their respective inputs CircleInput, SquareInput, and TriangleInput (which are disjoint) are already well-defined in this system?
Why should the users extend any of these inputs at all?
Isn't your pipeline essentially that a ShapeDependency is acted upon by some business logic to create ShapeInput and pass it to the correct Shape?
You could clarify this by clearly defining the responsibility of each class. I would expect the sole responsibility of CircleInput, SquareInput etc would be to just hold input data, not to perform business logic.
I would keep that business logic in its own class, maybe something like this:
abstract class BusinessLogic<S extends Shape, I> {
private final Function<I, S> shapeConstructor;
public BusinessLogic(Function<I, S> shapeConstructor) {
this.shapeConstructor = shapeConstructor;
}
protected abstract I createShapeInput(ShapeDependency shapeDependency);
public final S createShape(ShapeDependency shapeDependency) {
I shapeInput = createShapeInput(shapeDependency);
S shape = shapeConstructor.apply(shapeInput);
return shape;
}
}
class CircleBusinessLogic extends BusinessLogic<Circle, CircleInput> {
public CircleBusinessLogic() {
super(Circle::new);
}
#Override
protected CircleInput createShapeInput(ShapeDependency shapeDependency) {
return new CircleInput();
}
}
Let me know if this satisfies your requirements. If not, please clarify your goals and pipeline.
I can't get my head around the following OOP problem in java:
I have two classes which extend some basic library classes.
class myMovie extends Movie
{
int posi_x;
int posi_y;
...
myMovie(PApplet parent, String filename, int pposi_x, int pposi_y, float pangle, String player)
{
super(parent, filename);
...
}
int getFadeVal()
{
...
}
void fadeOut(int pms)
{
...
}
void fadeIn(int pms)
{
...
}
void exit()
{
...
}
}
class myImage extends PImage
{
// Will get a somehow similar implementation
}
This works as intended. But now I have a "main loop" which draws all of these different objects and therefore i want to simply call the methods of these classes without asking of which type the object next in list is.
For me that means i need some type of head class which contains either a myMovie or a myImage. Something like:
class AnimationObject
{
var child;
...
}
And then in the main loop just calling
AnimationObject[] ani_list;
foreach(AnimationObject ani in ani_list)
{
ani.draw();
}
Of course the problem is that Java doesn't know something like "var". I Could use Object, but then i'd have to always cast the type of the object in the main loop.
Which is the correct approach to this problem? I can't really understand all those Interfaces, Abstract Classes etc. in contrast to my exact problem.
Which is the preferred and correct way to do this?
}
Use a interface for this:
public interface AnimationObject {
void draw();
}
public class myImage extends PImage implements AnimationObject {
[...]
}
public class myMovie extends Movie implements AnimationObject {
[...]
}
And in your main loop use the interface:
AnimationObject[] ani_list;
foreach(AnimationObject ani : ani_list) {
ani.draw();
}
I have a simple Factory (GenericFudge) that creates objects of different types depending on external circumstances. Currently, my code looks something like this:
abstract class Fudge {
Fudge() {
}
void make() {
System.out.println("made.");
}
}
class VanillaFudge extends Fudge {
#Override
void make() {
System.out.print("Vanilla ");
super.make();
}
}
class ChocolateFudge extends Fudge {
#Override
void make() {
System.out.print("Chocolate ");
super.make();
}
}
class InvalidFlavorException extends Exception {};
// factory / proxy
public class GenericFudge {
Fudge mFudge = null;
GenericFudge(String flavor) throws InvalidFlavorException {
if (flavor.equals("Chocolate")) {
mFudge = new ChocolateFudge();
} else if (flavor.equals("Vanilla")) {
mFudge = new VanillaFudge();
}
}
void make() {
mFudge.make();
}
public static void main(String args[]) {
for (String flavor : new String[] {"Chocolate", "Vanilla"}) {
GenericFudge fudge;
try {
fudge = new GenericFudge(flavor);
fudge.make();
} catch (InvalidFlavorException e) {
System.out.println("Sorry, we don't make that flavor");
}
}
}
}
My goal is to get the details of chocolate and vanilla out of GenericFudge, so that when CaramelFudge is implemented, no changes to GenericFudge are required. For example, GenericFudge would iteratively call a "createIfItsMyFlavor()" method for every xxxFudge class. (In my actual application, I have to try them iteratively, but I'd be interested in other possibilities.)
My instinct was to use a static initializer per subclass (per xxxFudge) that adds "itself" to a list by calling a registerFudge method of GenericFudge, but this hits the chicken-and-egg problem (the class is never used, so its static initializer never gets invoked).
No doubt there's a better way I haven't envisioned. Thanks!
If you are using any kind of dependency injection system like Spring, this is easy to implement using #PostConstruct. If this works, then you can call a register method in GenericFudge from the method you annotate with PostConstruct. In GenericFudge, you have a map, and whenever addType is called you add it to the map. That way your GenericFudge remains unchanged, and new callers will register using PostConstruct. To simplify things further, you can define this in your base class Fudge, and pass the fudge name using the constructor, that way you don't have to declare the register method in each sub-class.
private String fudge;
public Fudge(final String fudge) {
this.fudge = fudge;
}
#Autowired
private GenericFudge fudge;
#PostConstruct
private void register() {
fudge.addType(fudge, this);
}
In GenericFudge
private Map<String, Fudge> fudgeTypes = Maps.newHashMap();
public void register(final String fudgeType, final Fudge fudgeInstance) {
fudgeTypes.put(fudgeType, fudgeInstance);
}
If you do not use any dependency injection system:
Another approach could be to have a static method in the base class Fudge, where you declare all the types of fudge and then return an instance based on the request. That way you don't modify the GenericFudge class, but only the base class of Fudge. This is not ideal, but it gets you away from having to modify the GenericFudge class, and instead of "registering" with something like PostConstruct, you put an entry into the Map.
Example (ImmutableMap from Guava, you can declare the map however you like , this is only for the example):
public abstract class Fudge {
private static final Map<String, Fudge> FUDGE_TYPES = ImmutableMap.of(
"Type1", new Type1Fudge(),
"Type2", new Type2Fudge()
// Add new entry when implemented
);
public static Fudge getFudge(final String fudge) {
if (FUDGE_TYPES.containsKey(fudge)) {
return FUDGE_TYPES.get(fudge);
} else {
// handle missing fudge depending on your preference
}
}
}
I have 2 Interfaces:
public interface Flash { public void flash(int level); } and
public interface SuperFlash extends Flash { public void flash(int level, boolean repeat); }
Then I have a custom collection class which should hold any number of things implementing Flash or SuperFlash. The class declaration looks something like
public class FlashyThings<? extends Flash>.
So the class can hold instances of type Flash and its subtype(s).
Inside the class FlashyThings, I am using an ArrayList to hold all of these objects:
private ArrayList<? extends Flash> things;
So far so good, now, when I try to iterate over the collection, is there a way to know/infer the dynamic type of the objects without using instanceof (as in the next snippet)?
for (Flash f : this.things) {
if (f instanceof SuperFlash) { // <-- :(
// SuperFlash things
} else {
// Flash things
}
}
This is the upper bounded side of the medal, now to the lower bounded side
To begin with, I had to change the class declaration to
public class FlashyThings
as lower bounded wildcards are not allowed in the class declaration. The ArrayList declaration now looks like:
private ArrayList<? super SuperFlash> things;
Now iterating over the collection becomes:
for (Object o : this.things) { // <-- :((
// All things are of type Object which is *really* not cool
if (o instanceof SuperFlash) { // <-- :(
// SuperFlash things
} else {
// Flash things
}
}
So I'm pretty much stuck where I began.
What would be the recommended way to iterate over such a construct? To summarise, what I want to achieve having is
the interface hierarchy described at the very top
the class FlashyThings being parameterisable
iterating over the ArrayList things, taking into account the dynamic type of its contents (without having to do the instanceof check)
What you need to do is create an abstract FlashyThing that does as much of the shared methods as possible in the abstract class, leaving only the stuff that is dependent on knowing you have a Flash or SuperFlash to the subclass. For example (publics and privates left out for brevity):
abstract class AbstractFlashyThing<F extends Flash> {
List<F> flashes;
AbstractFlashyThing() {
flashes = new ArrayList<F>();
}
void doOperations() {
for (F flash : flashes) {
doOperation(flash);
}
}
abstract void doOperation(F flash);
}
Note how the generic type F is used as a place holder wherever possible.
Example subclass
class SuperFlashyThing extends AbstractFlashyThing<SuperFlash> {
#Override
void doOperation(SuperFlash superFlash) {
// do super flash stuff
}
}
Subclass is a concrete implementation rather than a generic class, so its instatiation is as follows.
SuperFlashyThing thing = new SuperFlashyThing();
// as opposed to the following
SuperFlashyThing<SuperFlash> thing = new SuperFlashyThing<SuperFlash>();
Maybe I don't quite understand the problem, but why are you making everything so complicated, instead of just using polymorphism? This is what the Object Oriented Paradigm is designed to do. Example:
Flash.java
public class Flash {
public void doSomething() {
System.out.println("Flash doSomething()");
}
}
SuperFlash.java
public class SuperFlash extends Flash {
#Override
public void doSomething() {
System.out.println("SuperFlash doSomething()");
}
}
FlashyThings.java
public class FlashyThings {
private ArrayList<Flash> things = new ArrayList<>();
public ArrayList<Flash> getThings() {
return things;
}
public void doSomething(){
for (Flash thing : things) {
thing.doSomething();
}
}
}
ExampleMain.java
public class ExampleMain {
public static void main(String[] args) {
Flash first = new Flash();
SuperFlash second = new SuperFlash();
Flash third = new Flash();
FlashyThings things = new FlashyThings();
things.getThings().add(first);
things.getThings().add(second);
things.getThings().add(third);
things.doSomething();
}
}
What about using an enum ?
public enum FlashType
{
Flash, SuperFlash;
}
Add a method for checking the flash type of any object of type Flash:
public interface Flash
{
void flash(int level);
FlashType getType();
}
Then iterate over private ArrayList<? extends Flash> things;
for (Flash f : this.things)
{
if (f.getType() == FlashType.SuperFlash)
{
// SuperFlash things
}
else if (f.getType() == FlashType.Flash)
{
// Flash things
}
}
or iterate over ArrayList<? super SuperFlash> things;
for (Object o : this.things)
{
final Flash f = (Flash)o;//this cannot failed: SuperFlash extends Flash
if (f.getType() == FlashType.SuperFlash)
{
// SuperFlash things
}
else if (f.getType() == FlashType.Flash)
{
// Flash things
}
}