Java polymorphism: finding the right design pattern - java

Disclaimer: I know there are a lot of questions about polymorphism out there, but I couldn't find a suitable answer for my problem. If your Google-fu is better than mine, please forgive the dupe.
I have a model using inheritance, such as in the example below.
public abstract class Base {
// ...
}
public class ConcreteA extends Base {
private String someString;
// ...
}
public class ConcreteB extends Base {
private boolean someBool;
// ...
}
And I also have a List<Base>, which is composed of objects that are either ConcreteAs or ConcreteBs.
I need to generate a graphical view for each object in the list, but the resulting element is not the same for ConcreteAs and ConcreteBs. From the example above, the view for ConcreteA would be a text field, while the view for a ConcreteB would be a check box.
How can I achieve this using OO principles?

The problem that you have is that you somewhere return a List<Base> when the caller must know the concrete type.
Usually this is caused because one tried to make a method more generic. E.g. if someone has this service methods
public List<ConcreteA> doSomethingA(){ ... }
public List<ConcreteB> doSomethingB(){ ... }
he might think it is a better idea to introduce a superclass, Base so that both methods can be substituted by
public List<Base> doSomething(){ ... }
This is a good idea if the caller is only interessted in a Base object. This means that ConcreateA and ConcreteB have some common behavior that the caller only depends on.
But in your case it seems that the caller needs the concrete type information that is not available anymore, because of the more generic method.
So you either must preserve or reconstruct the type information.
Preserve the type by using a custom return type instead of making the method generic
public class Result {
private List<ConcreteA> concreteA;
private List<ConcreteB> concreteA;
}
public Result doSomething();
Recunstruct the type information using instanceof
Reconstruct the type information by introcucing a visitor pattern.

Not a pattern - this is what abstraction is all about. Declare a method you want all subclasses of Base to implement and each must implement it in their own way.
Obviously you would pass parameters and/or get results of the methods.
public abstract class Base {
abstract void graphicalView();
}
public class ConcreteA extends Base {
#Override
void graphicalView() {
}
}
public class ConcreteB extends Base {
#Override
void graphicalView() {
}
}
public void test() throws IOException {
List<Base> bases = new ArrayList<>();
for ( Base b : bases ) {
b.graphicalView();
}
}

I think you're looking for Visitor Design Pattern.
From Wikipedia :
In object-oriented programming and software engineering, the visitor
design pattern is a way of separating an algorithm from an object
structure on which it operates. A practical result of this separation
is the ability to add new operations to extant object structures
without modifying the structures. It is one way to follow the
open/closed principle.
In essence, the visitor allows adding new virtual functions to a
family of classes, without modifying the classes. Instead, a visitor
class is created that implements all of the appropriate
specializations of the virtual function. The visitor takes the
instance reference as input, and implements the goal through double
dispatch.

In such cases, I usually use generics something like this
public abstract class Base <T extends Shape>{
public abstract T drawShape();
}
public class ConcreatA extends Base<Circle> {
#Override
public Circle drawShape() {
return null;
}
}
public class ConcreatB extends Base<Square> {
#Override
public Square drawShape() {
return null;
}
}
So now you can use list of Shapes

Related

Java Multiple Inheritance

In an attempt to fully understand how to solve Java's multiple inheritance problems I have a classic question that I need clarified.
Lets say I have class Animal this has sub classes Bird and Horse and I need to make a class Pegasus that extends from Bird and Horse since Pegasus is both a bird and a horse.
I think this is the classic diamond problem. From what I can understand the classic way to solve this is to make the Animal, Bird and Horse classes interfaces and implement Pegasus from them.
I was wondering if there was another way to solve the problem in which I can still create objects for birds and horses. If there was a way to be able to create animals also that would be great but not necessary.
You could create interfaces for animal classes (class in the biological meaning), such as public interface Equidae for horses and public interface Avialae for birds (I'm no biologist, so the terms may be wrong).
Then you can still create a
public class Bird implements Avialae {
}
and
public class Horse implements Equidae {}
and also
public class Pegasus implements Avialae, Equidae {}
Adding from the comments:
In order to reduce duplicate code, you could create an abstract class that contains most of the common code of the animals you want to implement.
public abstract class AbstractHorse implements Equidae {}
public class Horse extends AbstractHorse {}
public class Pegasus extends AbstractHorse implements Avialae {}
Update
I'd like to add one more detail. As Brian remarks, this is something the OP already knew.
However, I want to emphasize, that I suggest to bypass the "multi-inheritance" problem with interfaces and that I don't recommend to use interfaces that represent already a concrete type (such as Bird) but more a behavior (others refer to duck-typing, which is good, too, but I mean just: the biological class of birds, Avialae). I also don't recommend to use interface names starting with a capital 'I', such as IBird, which just tells nothing about why you need an interface. That's the difference to the question: construct the inheritance hierarchy using interfaces, use abstract classes when useful, implement concrete classes where needed and use delegation if appropriate.
There are two fundamental approaches to combining objects together:
The first is Inheritance. As you have already identified the limitations of inheritance mean that you cannot do what you need here.
The second is Composition. Since inheritance has failed you need to use composition.
The way this works is that you have an Animal object. Within that object you then add further objects that give the properties and behaviors that you require.
For example:
Bird extends Animal implements IFlier
Horse extends Animal implements IHerbivore, IQuadruped
Pegasus extends Animal implements IHerbivore, IQuadruped, IFlier
Now IFlier just looks like this:
interface IFlier {
Flier getFlier();
}
So Bird looks like this:
class Bird extends Animal implements IFlier {
Flier flier = new Flier();
public Flier getFlier() { return flier; }
}
Now you have all the advantages of Inheritance. You can re-use code. You can have a collection of IFliers, and can use all the other advantages of polymorphism, etc.
However you also have all the flexibility from Composition. You can apply as many different interfaces and composite backing class as you like to each type of Animal - with as much control as you need over how each bit is set up.
Strategy Pattern alternative approach to composition
An alternative approach depending on what and how you are doing is to have the Animal base class contain an internal collection to keep the list of different behaviors. In that case you end up using something closer to the Strategy Pattern. That does give advantages in terms of simplifying the code (for example Horse doesn't need to know anything about Quadruped or Herbivore) but if you don't also do the interface approach you lose a lot of the advantages of polymorphism, etc.
I have a stupid idea:
public class Pegasus {
private Horse horseFeatures;
private Bird birdFeatures;
public Pegasus(Horse horse, Bird bird) {
this.horseFeatures = horse;
this.birdFeatures = bird;
}
public void jump() {
horseFeatures.jump();
}
public void fly() {
birdFeatures.fly();
}
}
May I suggest the concept of Duck-typing?
Most likely you would tend to make the Pegasus extend a Bird and a Horse interface but duck typing actually suggests that you should rather inherit behaviour. As already stated in the comments, a pegasus is not a bird but it can fly. So your Pegasus should rather inherit a Flyable-interface and lets say a Gallopable-interface.
This kind of concept is utilized in the Strategy Pattern. The given example actually shows you how a duck inherits the FlyBehaviour and QuackBehaviour and still there can be ducks, e.g. the RubberDuck, which can't fly. They could have also made the Duck extend a Bird-class but then they would have given up some flexibility, because every Duck would be able to fly, even the poor RubberDuck.
Technically speaking, you can only extend one class at a time and implement multiple interfaces, but when laying hands on software engineering, I would rather suggest a problem specific solution not generally answerable. By the way, it is good OO practice, not to extend concrete classes/only extend abstract classes to prevent unwanted inheritance behavior - there is no such thing as an "animal" and no use of an animal object but only concrete animals.
In Java 8 and later, you could use default methods to achieve a sort of C++-like multiple inheritance.
You could also have a look at this tutorial which shows a few examples that should be easier to start working with than the official documentation.
It is safe to keep a horse in a stable with a half door, as a horse cannot get over a half door. Therefore I setup a horse housing service that accepts any item of type horse and puts it in a stable with a half door.
So is a horse like animal that can fly even a horse?
I used to think a lot about multiple inheritance, however now that I have been programming for over 15 years, I no longer care about implementing multiple inheritance.
More often than not, when I have tried to cope with a design that pointed toward multiple inheritance, I have later come to release that I had miss understood the problem domain.
OR
If it looks like a duck and quacks like a duck but it needs
batteries, you probably have the wrong abstraction.
Java does not have a Multiple inheritance problem, since it does not have multiple inheritance. This is by design, in order to solve the real multiple inheritance problem (The diamond problem).
There are different strategies for mitigating the problem. The most immediately achievable one being the Composite object that Pavel suggests (essentially how C++ handles it). I don't know if multiple inheritence via C3 linearization (or similar) is on the cards for Java's future, but I doubt it.
If your question is academic, then the correct solution is that Bird and Horse are more concrete, and it is false to assume that a Pegasus is simply a Bird and a Horse combined. It would be more correct to say that a Pegasus has certain intrinsic properties in common with Birds and Horses (that is they have maybe common ancestors). This can be sufficiently modeled as Moritz' answer points out.
I think it depends very much on your needs, and how your animal classes are to be used in your code.
If you want to be able to make use of methods and features of your Horse and Bird implementations inside your Pegasus class, then you could implement Pegasus as a composition of a Bird and a Horse:
public class Animals {
public interface Animal{
public int getNumberOfLegs();
public boolean canFly();
public boolean canBeRidden();
}
public interface Bird extends Animal{
public void doSomeBirdThing();
}
public interface Horse extends Animal{
public void doSomeHorseThing();
}
public interface Pegasus extends Bird,Horse{
}
public abstract class AnimalImpl implements Animal{
private final int numberOfLegs;
public AnimalImpl(int numberOfLegs) {
super();
this.numberOfLegs = numberOfLegs;
}
#Override
public int getNumberOfLegs() {
return numberOfLegs;
}
}
public class BirdImpl extends AnimalImpl implements Bird{
public BirdImpl() {
super(2);
}
#Override
public boolean canFly() {
return true;
}
#Override
public boolean canBeRidden() {
return false;
}
#Override
public void doSomeBirdThing() {
System.out.println("doing some bird thing...");
}
}
public class HorseImpl extends AnimalImpl implements Horse{
public HorseImpl() {
super(4);
}
#Override
public boolean canFly() {
return false;
}
#Override
public boolean canBeRidden() {
return true;
}
#Override
public void doSomeHorseThing() {
System.out.println("doing some horse thing...");
}
}
public class PegasusImpl implements Pegasus{
private final Horse horse = new HorseImpl();
private final Bird bird = new BirdImpl();
#Override
public void doSomeBirdThing() {
bird.doSomeBirdThing();
}
#Override
public int getNumberOfLegs() {
return horse.getNumberOfLegs();
}
#Override
public void doSomeHorseThing() {
horse.doSomeHorseThing();
}
#Override
public boolean canFly() {
return true;
}
#Override
public boolean canBeRidden() {
return true;
}
}
}
Another possibility is to use an Entity-Component-System approach instead of inheritance for defining your animals. Of course this means, that you will not have individual Java classes of the animals, but instead they are only defined by their components.
Some pseudo code for an Entity-Component-System approach could look like this:
public void createHorse(Entity entity){
entity.setComponent(NUMER_OF_LEGS, 4);
entity.setComponent(CAN_FLY, false);
entity.setComponent(CAN_BE_RIDDEN, true);
entity.setComponent(SOME_HORSE_FUNCTIONALITY, new HorseFunction());
}
public void createBird(Entity entity){
entity.setComponent(NUMER_OF_LEGS, 2);
entity.setComponent(CAN_FLY, true);
entity.setComponent(CAN_BE_RIDDEN, false);
entity.setComponent(SOME_BIRD_FUNCTIONALITY, new BirdFunction());
}
public void createPegasus(Entity entity){
createHorse(entity);
createBird(entity);
entity.setComponent(CAN_BE_RIDDEN, true);
}
you can have an interface hierarchy and then extend your classes from selected interfaces :
public interface IAnimal {
}
public interface IBird implements IAnimal {
}
public interface IHorse implements IAnimal {
}
public interface IPegasus implements IBird,IHorse{
}
and then define your classes as needed, by extending a specific interface :
public class Bird implements IBird {
}
public class Horse implements IHorse{
}
public class Pegasus implements IPegasus {
}
Ehm, your class can be the subclass for only 1 other, but still, you can have as many interfaces implemented, as you wish.
A Pegasus is in fact a horse (it is a special case of a horse), which is able to fly (which is the "skill" of this special horse). From the other hand, you can say, the Pegasus is a bird, which can walk, and is 4legged - it all depends, how it is easier for you to write the code.
Like in your case you can say:
abstract class Animal {
private Integer hp = 0;
public void eat() {
hp++; 
}
}
interface AirCompatible {
public void fly();
}
class Bird extends Animal implements AirCompatible {
#Override
public void fly() {
//Do something useful
}
}
class Horse extends Animal {
#Override
public void eat() {
hp+=2; 
}
}
class Pegasus extends Horse implements AirCompatible {
//now every time when your Pegasus eats, will receive +2 hp
#Override
public void fly() {
//Do something useful
}
}
Interfaces don't simulate multiple inheritance. Java creators considered multiple inheritance wrong, so there is no such thing in Java.
If you want to combine the functionality of two classes into one - use object composition. I.e.
public class Main {
private Component1 component1 = new Component1();
private Component2 component2 = new Component2();
}
And if you want to expose certain methods, define them and let them delegate the call to the corresponding controller.
Here interfaces may come handy - if Component1 implements interface Interface1 and Component2 implements Interface2, you can define
class Main implements Interface1, Interface2
So that you can use objects interchangeably where the context allows it.
So in my point of view, you can't get into diamond problem.
As you will already be aware, multiple inheritance of classes in Java is not possible, but it's possible with interfaces. You may also want to consider using the composition design pattern.
I wrote a very comprehensive article on composition a few years ago...
https://codereview.stackexchange.com/questions/14542/multiple-inheritance-and-composition-with-java-and-c-updated
Define interfaces for defining the capabilities. You can define multiple interfaces for multiple capabilities. These capabilities can be implemented by specific Animal or Bird.
Use inheritance to establish relationships among classes by sharing non-static and non-public data/methods.
Use Decorator_pattern to add capabilities dynamically. This will allow you to reduce number of inheritance classes & combinations.
Have a look at below example for better understanding
When to Use the Decorator Pattern?
To reduce the complexity and simplify the language, multiple inheritance is not supported in java.
Consider a scenario where A, B and C are three classes. The C class inherits A and B classes. If A and B classes have same method and you call it from child class object, there will be ambiguity to call method of A or B class.
Since compile time errors are better than runtime errors, java renders compile time error if you inherit 2 classes. So whether you have same method or different, there will be compile time error now.
class A {
void msg() {
System.out.println("From A");
}
}
class B {
void msg() {
System.out.println("From B");
}
}
class C extends A,B { // suppose if this was possible
public static void main(String[] args) {
C obj = new C();
obj.msg(); // which msg() method would be invoked?
}
}
To solve the problem of mutiple inheritance in Java → interface is used
J2EE (core JAVA) Notes By Mr. K.V.R Page 51
Day - 27
Interfaces are basically used to develop user defined data types.
With respect to interfaces we can achieve the concept of multiple inheritances.
With interfaces we can achieve the concept of polymorphism, dynamic binding and hence we can improve the performance of a JAVA program in
turns of memory space and execution time.
An interface is a construct which contains the collection of purely
undefined methods or an interface is a collection of purely abstract
methods.
[...]
Day - 28:
Syntax-1 for reusing the features of interface(s) to class:
[abstract] class <clsname> implements <intf 1>,<intf 2>.........<intf n>
{
variable declaration;
method definition or declaration;
};
In the above syntax clsname represents name of the class which is
inheriting the features from ‘n’ number of interfaces. ‘Implements’ is
a keyword which is used to inherit the features of interface(s) to a
derived class.
[...]
Syntax-2 inheriting ‘n’ number of interfaces to another interface:
interface <intf 0 name> extends <intf 1>,<intf 2>.........<intf n>
{
variable declaration cum initialization;
method declaration;
};
[...]
Syntax-3:
[abstract] class <derived class name> extends <base class name> implements <intf 1>,<intf 2>.........<intf n>
{
variable declaration;
method definition or declaration;
};
Problem not solved. To sufficiently model this out and to prevent code replication you'd either need multiple inheritance or mixins. Interfaces with default functions are not sufficient because you cannot hold members in interfaces.
Interface modeling leads to code replication in subclasses or statics, which is both evil.
All you can do is to use a custom construction and split it up in more components and compose it all together...
toy language

Abstract method with variable list of arguments

I haven't quite found an elegant way to solve this issue. I have an abstract class that several other classes are inheriting with an abstract method that can contain anywhere from zero to 4-5 arguments of varying types.
public abstract class Item {
public abstract void use();
}
For instance, I have a Book class that inherits this and takes no arguments when overriding use(), I have a Key class that inherits and takes a String and a Queue as arguments when overriding, etc...
I've tried using generics but I have to input the number used, such as Item, when it actually depends on the class.
public abstract class Item<T,U> {
public abstract void use(T arg1, U arg2); //Number of arguments/types could be more or less
}
I've tried sending a variable list of Objects but the object types are always variable and I've unsure as to the syntax to receive in the inheriting classes.
public abstract class Item<T> {
public abstract void use(T... arguments);
}
public class Book extends Item<?> {
public void use(?);
}
public class Book extends Item<String, Queue> { //Wrong number of arguments since I can't use Item<T...>
public void use(String str, Queue q); //fails
}
I may just be doing something wrong - can anyone offer any assistance or insight?
I've struggled with the same question, and there's not a perfect answer, but I can give you a few things to consider. First, you're basically trying to do something that is inherently against Object Oriented Programming, which is that you're trying to create a variable interface. The point of an interface is that code that gets an abstract version of the object (the Item rather than the Book, for example), knows how to invoke the use() method. This means that they must know what can be passed to the use() method. If the answer depends on the implementation of the abstract class or interface, then you need to ensure that the code using it actually knows what kind of implementation (Book, etc.) that it's using, otherwise it's not going to know how to invoke use() with the appropriate parameters anyway. It sounds like you need to refactor your code, in all honesty.
However, there is a way to answer your question as stated without refactoring the architecture. You could create a class that's data is all of the different types of parameters that could possibly be passed to the use() method, have the calling code set the fields of that class, and then pass that to the use() method. For example:
public class UseParameters {
private String string;
private Queue queue;
// Any other potential parameters to use(...)
public void setString(String string) {
this.string = string;
}
public String getString() {
return string;
}
// All of the other accessor methods, etc.
}
Then, you could define the use method in Item like this:
public abstract void use(UseParameters params);
And any code using an Item would have to set the parameters of the object appropriately:
Item item = // However you're going to get the item
UseParameters params = new UseParameters();
params.setString("good string");
params.setQueue(new Queue());
item.use(params);
I just want to point out that if the code above knows the Item is a Book (which is how it knows to set the String and Queue, then why not just get a Book and skip needing an abstract class with a variable use() method altogether? But I digress. Anyway, the Book would then implement the use() method like so:
#Override
public void use(UseParameters params) {
if(params.getString == null || params.getQueue() == null)
// throw exception
// Do what books do with strings and queues
}
I think that gets you what you want, but you should consider refactoring, I think.
What you want is the Value Object Pattern.
Define a class that encapsulates the various parameter types into one value object, and have the abstract method accept a parameter of this type. Each variation of parameters you were considering would have its own value class.
Then simply add a generic type to the class and have the abstract method accept a parameter of that type:
public abstract class Item<V> {
public abstract void use(V v);
}
To use it, suppose MyItem needs a value object of type MyValueClass:
public class MyItem extends Item<MyValueClass> {
public void use(MyValueClass v) {
}
}
If the types to be used as argument are always variable I don't see a reason to use generics. Just use plain Object type:
public abstract class Item {
public abstract void use(Object ... arguments);
}
public class Book extends Item {
public void use(Object ... arguments) { ... }
}
The best approach I can think of is to group the items according to the behavior of their use() method.
Example
public abstract class QueueableItem {
public abstract void use(String, Queue);
}
public abstract class OrdinaryItem{
public abstract void use(String);
}
If the grouped items share a common behavior (common as in same method signature & return value), you can define and extend a parent class that will contain the definition of this common behavior.
Yes, we can provide parameters to abstract method but it is must to provide same type of parameters to the implemented methods we wrote in the derived classes.

Handling all subtypes of a supertype

What is the best way to handle different subtypes of an abstract supertype as an argument, for instance when handling events.
The situation is as follows:
The supertype:
public interface MySuperInterface {
}
A subtype
public class SubclassA implements MySuperInterface {
}
Another subtype
public class SubclassB implements MySuperInterface {
}
Some class that should be able to handle any subtype of MySuperInterface
public class MySuperHandler {
public void handle(MySuperInterface mysuper) {
//do it
}
}
My different approaches are
a switch/case statement in the handler method. (which I dont like)
a method receive(MySuperHandler) in the interface and a dispatch to this method
inside the handle method: mysuper.receive(this) (which means the interface knows the handler class)
Adding a handle method for every subtype in the MySuperHandler class (this does not ensure that every subtype can be handled)
but for the mentioned reasons I'm not content with these solutions.
are there any options to handle this situation?
thanks
One approach is to use the Visitor Pattern. It would look something like this:
public interface MySuperInterface {
<T> T acceptVisitor(MySuperInterfaceVisitor<T>);
}
public interface MySuperInterfaceVisitor<T> {
T visitA(SubclassA a);
T visitB(SubclassB a);
}
public class SubclassA implements MySuperInterface {
<T> T acceptVisitor(MySuperInterfaceVisitor<T> visitor) {
return visitor.visitA(this);
}
}
public class SubclassB implements MySuperInterface {
<T> T acceptVisitor(MySuperInterfaceVisitor<T> visitor) {
return visitor.visitB(this);
}
}
public class MySuperHandler implements MySuperInterfaceVisitor<Foo>{
Foo visitA(SubclassA a) {
// construct Foo from SubclassA instance
}
Foo visitB(SubclassB a) {
// construct Foo from SubclassB instance
}
}
This is a bit like your #2, except the interface (and the subclasses) don't need to know about the handler. They just need to know about the visitor interface. This is good if you don't want MySuperInterface and its implementations to know about your specific handlers.
BTW, instead of calling:
myHandler.handle(myImpl);
you'd call:
myImpl.acceptVisior(myHandler);
This approach is nice if you want to ensure that every handler can handle every implementation of your interface, yet still keep the implementations from knowing about all of the "handlers" that exist.
If you add another implementation of your interface (MySuperInterface) the compiler will force you to add an acceptVisitor method. This method can either use one of the existing visit* methods, or you'll have to go and add a new one to the visitor interface. If you do the latter, you must then update all of the visitor (aka "handler") implementations. This ensures that every subtype can be handled, going forward.
This approach is more complex than the one in assylias's answer, and only really makes sense if you either want to break the coupling between the implementations of MySuperInterface and your handler code, or you have a strong desire to organize your handler code such that all of the code for a particular type of handling is "together".
One common use of the visitor pattern is rendering objects in different ways. Suppose you want to be able to convert an object into a PDF or HTML. You could have a toHTML and a toPDF method in your interface. The downside to this approach is that now your classes are dependent upon your libraries for generating HTML and PDF. Also, if someone later wants to add a new type of output they need to modify these core classes, which may be undesirable. With the visitor pattern, only the vistior classes need to know about the PDF or HTMl libraries, and new visitors can be added without modifying the core classes. (But again, adding new core classes means you either need to have them reuse an existing visit* method, or you'll have to modify all of the visitor implementations.)
Your description is a bit vague but if you have several subclasses, some of which share a common "handle" behavior, this could work - if you only have 2 subclasses and don't plan to have more in the future, the Abstract step is probably unnecessary:
public interface MySuperInterface {
void handle();
}
public abstract AbstractMySuperInterface {
public void handle() {
//implement default behavior
}
}
public class SubclassA implements MySuperInterface {
//nothing here, just use default behavior
}
public class SubclassB implements MySuperInterface {
public void handle() {
//implement another behavior
}
}
public class MySuperHandler {
public void handle(MySuperInterface mysuper) {
mysuper.handle();
}
}

Implicit object type in Java?

This isn't exactly the definition of implicit type conversion, but I'm curious how many standards I'm breaking with this one...
I'm creating an abstract class in Java that basically casts its variables depending on a string passed into the constructor.
For example:
public abstract class MyClass {
Object that;
public MyClass(String input){
if("test1".equals(input){
that = new Test1();
}
else{
that = new Test();
}
}
public void doSomething(){
if(that instanceof Test1){
//specific test1 method or variable
} else if(that instanceof Test2)}
//specific test2 method or variable
} else {
//something horrible happened
}
}
}
You see what I'm getting at? Now the problem I run into is that my compiler wants me to explicitly cast that into Test1 or Test2 in the doSomething method - which I understand, as the compiler won't assume that it's a certain object type even though the if statements pretty much guarantee the type.
I guess what I'm getting at is, is this a valid solution?
I have other classes that all basically do the same thing but use two different libraries depending on a simple difference and figure this class can help me easily track and make changes to all of those other objects.
You are right. This is a horrible way to achieve polymorphism in design. Have you considered using a factory? A strategy object? It sounds like what you are trying to achieve can be implemented in a more loosely-coupled way using a combination of these patterns (and perhaps others).
For the polymorphism of doSomething, for example:
interface Thing {
public void doThing();
}
class Test1 implements Thing {
public void doThing() {
// specific Test1 behavior
}
}
class Test2 implements Thing {
public void doThing() {
// specific Test2 behavior
}
}
class MyClass {
Thing _thing;
public void doSomething() {
_thing.doThing(); // a proper polymorphism will take care of the dispatch,
// effectively eliminating usage of `instanceof`
}
}
Of course, you need to unify the behaviors of Test1 and Test2 (and other concrete Thing classes, present and planned) under a set of common interface(s).
PS: This design is commonly known as Strategy Pattern.
I would create a separate class file. So you would have something like this:
1. You abstract "MyClass"
->within "MyClass" define an abstract method call doSomething...this will force the specific implementation of the method to it's subclasses.
2. Test1 would be the implementation of MyClass which would contain the implementation of the doSomething method
3. Create a utility class that does the check "instanceOf" that check should not be in the constructor it belongs in another class.
So in the end you would have 3 class files an Abstract Class, Implementation of the Abstract and a Class that does the "instanceOf" check. I know this sounds like a lot but it's the proper way to design, for what I think you are attempting to do. You should pick up a design patterns book, I think it would help you a lot with questions like these.
The Open-Closed principle would be better satisfied by moving the object creation outside of this class.
Consider changing the constructor to accept an object that implements an interface.
public MyClass {
public MyClass( ITest tester ) { m_tester = tester; }
public void doSomething(){ m_tester.doTest(); }
}
This makes it possible to change the behavior of the class (open to extension) without modifying its code (closed to modification).
The better way to do this is to create an interface which will specify a set of methods that can be guaranteed to be called on the object.
Here's an example:
public interface TestInterface
{
void doTest();
}
Now you can write your classes to implement this interface. This means that you need to provide a full definition for all methods in the interface, in this case doTest().
public class Test implements TestInterface
{
public void doTest()
{
// do Test-specific stuff
}
}
public class Test1 implements TestInterface
{
public void doTest()
{
// do Test1-specific stuff
}
}
Looks really boring and pointless, right? Lots of extra work, I hear you say.
The true value comes in the calling code...
public abstract class MyObject
{
Test that;
// [...]
public void doSomething()
{
that.doTest();
}
}
No if statements, no instanceof, no ugly blocks, nothing. That's all moved to the class definitions, in the common interface method(s) (again, here that is doTest()).

Practical side of the ability to define a class within an interface in Java?

What would be the practical side of the ability to define a class within an interface in Java:
interface IFoo
{
class Bar
{
void foobar ()
{
System.out.println("foobaring...");
}
}
}
I can think of another usage than those linked by Eric P: defining a default/no-op implementation of the interface.
./alex
interface IEmployee
{
void workHard ();
void procrastinate ();
class DefaultEmployee implements IEmployee
{
void workHard () { procrastinate(); };
void procrastinate () {};
}
}
Yet another sample — implementation of Null Object Pattern:
interface IFoo
{
void doFoo();
IFoo NULL_FOO = new NullFoo();
final class NullFoo implements IFoo
{
public void doFoo () {};
private NullFoo () {};
}
}
...
IFoo foo = IFoo.NULL_FOO;
...
bar.addFooListener (foo);
...
I think this page explains one example pretty well. You would use it to tightly bind a certain type to an interface.
Shamelessly ripped off from the above link:
interface employee{
class Role{
public String rolename;
public int roleId;
}
Role getRole();
// other methods
}
In the above interface you are binding the Role type strongly to the employee interface(employee.Role).
One use (for better or worse) would be as a workaround for the fact that Java doesn't support static methods in interfaces.
interface Foo {
int[] getData();
class _ {
static int sum(Foo foo) {
int sum = 0;
for(int i: foo.getData()) {
sum += i;
}
return sum;
}
}
}
Then you'd call it with:
int sum = Foo._.sum(myFoo);
I can say without hesitation that I've never done that. I can't think of a reason why you would either. Classes nested within classes? Sure, lots of reasons to do that. In those cases I tend to consider those inner classes to be an implementation detail. Obviously an interface has no implementation details.
One place this idiom is used heavily is in XMLBeans. The purpose of that project is to take an XML Schema and generate a set of Java classes that you can use bidirectionally to work with XML documents corresponding to the schema. So, it lets you parse XML into xml beans or create the xml beans and output to xml.
In general, most of the xml schema types are mapped to a Java interface. That interface has within it a Factory that is used to generate instances of that interface in the default implementation:
public interface Foo extends XmlObject {
public boolean getBar();
public boolean isSetBar();
public void setBar(boolean bar);
public static final SchemaType type = ...
public static final class Factory {
public static Foo newInstance() {
return (Foo)XmlBeans.getContextTypeLoader().newInstance(Foo.type, null);
}
// other factory and parsing methods
}
}
When I first encountered this it seemed wrong to bind all this implementation gunk into the interface definition. However, I actually grew to like it as it let everything get defined in terms of interfaces but have a uniform way to get instances of the interface (as opposed to having another external factory / builder class).
I picked it up for classes where this made sense (particularly those where I had a great deal of control over the interface/impls) and found it to be fairly clean.
I guess you could define a class that is used as the return type or parameter type for methods within the interface. Doesn't seem particularly useful. You might as well just define the class separately. The only possible advantage is that it declares the class as "belonging" to the interface in some sense.
Google Web Toolkit uses such classes to bind 'normal' interface to asynchronous call interface:
public interface LoginService extends RemoteService {
/**
* Utility/Convenience class.
* Use LoginService.App.getInstance() to access static instance of LoginServiceAsync
*/
class App {
public static synchronized LoginServiceAsync getInstance() {
...
}
}
}
With a static class inside an interface you have the possibility to shorten a common programming fragment: Checking if an object is an instance of an interface, and if so calling a method of this interface. Look at this example:
public interface Printable {
void print();
public static class Caller {
public static void print(Object mightBePrintable) {
if (mightBePrintable instanceof Printable) {
((Printable) mightBePrintable).print();
}
}
}
}
Now instead of doing this:
void genericPrintMethod(Object obj) {
if (obj instanceof Printable) {
((Printable) obj).print();
}
}
You can write:
void genericPrintMethod(Object obj) {
Printable.Caller.print(obj);
}
Doing this seems to have "Bad design decision" written all over it.
I would urge caution whenever it seems like a good idea to create a non-private nested class. You are almost certainly better off going straight for an outer class. But if you are going to create a public nested class, it doesn't seem any more strange to put it in an interface than a class. The abstractness of the outer class is not necessarily related to the abstractness of a nested class.
This approach can be used to define many classes in the same file. This has worked well for me in the past where I have many simple implementations of an interface. However, if I were to do this again, I would use an enum which implements an interface which would have been a more elegant solution.

Categories

Resources