I'm trying to do something along the lines:
abstract class Base {}
public interface One {...}
public interface Two {...}
public class A extends Base implements One {...}
public class B extends Base implements One, Two {...}
public class C extends Base implements Two {...}
public class Container
{
class Handler
{
public void doSomething(A obj){System.out.println("A");}
public void doSomething(B obj){System.out.printLn("B");}
public void doSomething(C obj){System.out.println("C");}
}
Base base;
Handler handler;
public Container(Base base)
{
this.base = base;
this.handler=new Handler();
}
public void set(Base base)
{
this.base=base;
}
public void go()
{
this.handler.doSomething(this.base);
}
}
Container con=new Container(new A());
con.go();
con.set(new B());
con.go();
Where the output would end up being "A" "B", but I'm running into problems dynamically casting Container.base to the appropriate class;
The closest solution I have found is in the Container.go function add in an if else chain checking the instanceOf the class and casting the parameter to the corresponding class then calling handler.doSomething in each if block.
public void go()
{
if(this.base instanceOf A)
{
this.handler.doSomething((A)this.base);
}
else if(this.base instanceOf B)
....
}
Is there a better way to go about this?
Which method is called is determined at compile time and not at run time so dynamic casting isn't going to work without some reflection or other tinkering about. I would suggest a better approach is to move the logic for
public void doSomething(A obj){System.out.println("A");}
public void doSomething(B obj){System.out.printLn("B");}
public void doSomething(C obj){System.out.println("C");}
Into the the specific classes. For example:
abstract class Base {
absract public void doSomething();
}
public class A extends Base implements One {
public void doSomething() {System.out.printLn("A");}
}
...
class Handler {
public void doSomething(Base obj){obj.doSomething();}
}
Now your handler doesn't need to care about the specific class of a Base object it is getting.
You could use the visitor pattern:
public interface Visitor {
public void doSomething(A obj);
public void doSomething(B obj);
public void doSomething(C obj);
}
Declare an abstract method in Base (or in a new interface):
abstract class Base {
public abstract void accept(Visitor v);
}
and implement it in A, B, C:
public class A extends Base implements One {
#Override
public void accept(Visitor v) {
v.doSomething(this);
}
...
}
public class B extends Base implements One, Two {
#Override
public void accept(Visitor v) {
v.doSomething(this);
}
...
}
public class C extends Base implements Two {
#Override
public void accept(Visitor v) {
v.doSomething(this);
}
...
}
Handler implements Visitor:
class Handler implements Visitor {
#Override
public void doSomething(A obj){
System.out.println("A");
}
#Override
public void doSomething(B obj){
System.out.printLn("B");
}
#Override
public void doSomething(C obj){
System.out.println("C");
}
}
And finally, go becomes:
public void go() {
this.base.visit(this.handler);
}
UPDATE
Note that #Evan Jones' solution is simpler and it could be what you need. The visitor pattern is used when you want to separate the implementations of the doSomething methods from the A, B, C classes and/or you want the ability to add new operations without changing these classes.
Related
My program takes data from different file types and inserts them into different DBs depending on the department which uploaded the file.
To accomplish this, I have a base abstract class AbstractHandler which has some methods which are unimplemented and some which are common to all children. Two types of abstract classes extend from this class, InputTypeAHandler, InputTypeBHandler, etc. and OutputTypeAHandler, OutputTypeBHandler, etc. These abstract classes also implement some more methods but not all.
I have concrete classes which I want to extend from these two types of classes and which will implement some more methods specific to every class. For example,
abstract class AbstractHandler {
public void method1() {
// ....
}
public abstract void method2();
public abstract void method3();
public abstract void method4();
}
abstract class InputTypeAHandler extends AbstractHandler {
#Override
public void method2() {
// ....
}
}
abstract class OutputTypeBHandler extends AbstractHandler {
#Override
public void method3() {
// ....
}
}
public class ConcreteHandler1 extends InputTypeAHandler, OutputTypeBHandler {
#Override
public void method4() {
// ....
}
}
public class ConcreteHandler2 extends InputTypeCHandler, OutputTypeAHandler {
#Override
public void method4() {
// ....
}
}
Since Java does not allow multiple inheritance, how do I do this?
You seem to implement some kind of conversion between any pair of A,B,C... types (perhaps formats?). If it is the case, the AbstractHandler probably has multiple responsibilities. Split its logic to part involving source format and part involving target format. You can inspire in converter pattern or GoF Bridge pattern.
I use lombok and the power of interfaces for this:
public class Test implements InputTypeAHandler,OutputTypeAHandler {
#Delegate
OutputTypeAHandlerImp outputTypeAHandlerImp = new OutputTypeAHandlerImp() {
#Override
String id() {
return "mellow";
}
};
#Delegate
InputTypeAHandlerImp inputTypeAHandler = new InputTypeAHandlerImp(){
#Override
String id() {
return "hello124";
}
};
}
public static abstract class OutputTypeAHandlerImp implements OutputTypeAHandler {
abstract String id();
#Override
public void write(String s) {
System.out.println(s);
}
}
public static abstract class InputTypeAHandlerImp implements InputTypeAHandler {
abstract String id();
#Override
public String read() {
return new Scanner(System.in).nextLine();
}
}
public interface InputTypeAHandler {
String read();
}
public interface OutputTypeAHandler{
void write(String s);
}
Let me describe my intention with an example,
class Base {
public void sayHi() {
System.out.println("Hi");
}
}
class ChildOne extends Base {
public void sayBye() {
System.out.println("Bye-1");
}
}
class ChildTwo extends Base {
public void sayBye() {
System.out.println("Bye-2");
}
}
public class MainClass {
public static <T extends Base> void genericFunction(T child) {
child.sayBye();
}
public static void main(String[] args) {
ChildOne childOne = new ChildOne();
ChildTwo childTwo = new ChildTwo();
genericFunction(childOne);
genericFunction(childTwo);
}
}
This code is wrong. But my intention is the child class (some already existing classes in a project) which has similar properties between them are they extend the base class and have sayBye() member function.
Is there a way to pass all the child classes as parameter to a generic function and to call the member function sayBye() (as per this example)?
Sure, you can either create a common base class or common interface for all the classes that have a sayBye method.
Then you can change the type bound of your generic type parameter:
public static <T extends CommonInterface> void genericFunction(T child) {
child.sayBye();
}
or without generics:
public static void nonGenericFunction(CommonInterface child) {
child.sayBye();
}
You can bring common functionality together without adjusting the hierarchy by introducing an interface that defines it and creating empty classes extending the common objects.
class Base {
public void sayHi() {
System.out.println("Hi");
}
}
class ChildOne extends Base {
public void sayBye() {
System.out.println("Bye-1");
}
}
class ChildTwo extends Base {
public void sayBye() {
System.out.println("Bye-2");
}
}
// The common functionality I want to use.
interface Bye {
public void sayBye();
}
class ChildOneBye extends ChildOne implements Bye {
// Don't need anything here.
}
class ChildTwoBye extends ChildTwo implements Bye {
// Don't need anything here.
}
public static <T extends Bye> void genericFunction(T child) {
child.sayBye();
}
public void test(String[] args) {
Bye childOne = new ChildOneBye();
Bye childTwo = new ChildTwoBye();
genericFunction(childOne);
genericFunction(childTwo);
}
One way is to mark the base class as abstract and have an abstract method sayBye(). In this way you don't need to change anything else in your codebase.
abstract class Base {
public void sayHi() {
System.out.println("Hi");
}
public abstract void sayBye();
}
Another approach is to use interface ByeInterface and use it to call sayBye(). Here is the with the required changes.
interface ByeInterface {
void sayBye();
}
class Base {
public void sayHi() {
System.out.println("Hi");
}
}
class ChildOne extends Base implements ByeInterface {
public void sayBye() {
System.out.println("Bye-1");
}
}
class ChildTwo extends Base implements ByeInterface {
public void sayBye() {
System.out.println("Bye-2");
}
}
public class MainClass {
public static <T extends ByeInterface> void genericFunction(T child) {
child.sayBye();
}
public static void main(String[] args) {
ChildOne childOne = new ChildOne();
ChildTwo childTwo = new ChildTwo();
genericFunction(childOne);
genericFunction(childTwo);
}
}
This approach can be used if you can not mark your base class as abstract class. Using interface, you can even call it without using generic.
public static void nonGenericFunction(ByeInterface child) {
child.sayBye();
}
I have two abstract generic classes. They cooperate and hence depend on each other. Occasionally one needs to pass this to the other. I am trying to find a type safe way to do this:
public abstract class AbstractA<T extends AbstractB<? extends AbstractA<T>>> {
protected void foo() {
T aB = createB();
aB.setA(this);
}
/** factory method */
abstract public T createB();
}
public abstract class AbstractB<T extends AbstractA<? extends AbstractB<T>>> {
private T theA;
#SuppressWarnings("unchecked")
public void setA(AbstractA<? extends AbstractB<?>> theA) { // dreamed of parameter list (T theA)
// Unchecked cast from AbstractA<capture#1-of ? extends AbstractB<?>> to T
this.theA = (T) theA;
}
protected T getA() {
return theA;
}
}
My question is whether I can find a cleaner way so I avoid the unchecked cast in AbstractB.setA(). I had hoped to declare it setA(T theA), but then the call to it won’t compile: The method setA(capture#1-of ? extends AbstractA<T>) in the type AbstractB<capture#1-of ? extends AbstractA<T>> is not applicable for the arguments (AbstractA<T>). I am still struggling to understand whether the compiler should know enough to allow it or not.
I was thinking my problem may be related to the one discussed in Java generics compilation error - The method method(Class<capture#1-of ? extends Interface>) in the type <type> is not applicable for the arguments. My unchecked cast was inspired from there. I liked the reply by Tom Hawtin - tackling, but I have not found a way to apply it to my situation.
My user will declare concrete subclasses and instantiate one ConcreteA and any number of ConcreteBs:
public class ConcreteA extends AbstractA<ConcreteB> {
#Override
public ConcreteB createB() {
return new ConcreteB();
}
public void concreteAMethod() {
// ...
}
}
public class ConcreteB extends AbstractB<ConcreteA> {
public void bar() {
ConcreteA a = getA();
a.concreteAMethod();
}
}
(class AbstractA<T extends AbstractB<? extends AbstractA<T>>> looks a bit complicated; I thought I needed it for concrete subclasses to know each other’s exact types, but apparently it doesn’t give me that.)
If I've understood you correctly, this should create the binding you want.
class Demo {
public static void main(String[] args) {
ConcreteA a = new ConcreteA();
ConcreteB b = new ConcreteB();
a.foo(b);
b = (ConcreteB) a.getB();
}
}
abstract class AbstractA<T extends AbstractB<?>>{
private AbstractB<?> b;
public AbstractB<?> getB(){
return b;
}
void foo(AbstractB<?> aB) {
b = aB;
aB.bar(this);
}
}
abstract class AbstractB<T extends AbstractA<?>> {
private AbstractA<?> a;
public AbstractA<?> getA(){
return a;
}
public void bar(AbstractA<?> theA) {
a = theA;
theA.foo(this);
}
}
class ConcreteA extends AbstractA<ConcreteB>{
}
class ConcreteB extends AbstractB<ConcreteA>{
}
I think this is what you ended up at yourself. I am not able to remove the cast to ConcreteB, getB() simply cannot be sure of the type it is holding. I now see why you had multiple generic statements in your declaration. :)
If you're up for it, continue searching, and post your own answer if you find one, I'd love to see it.
I hope solving half your problem counts for anything. ;)
I think I got it now why I cannot declare public void setA(T theA) in AbstractB and then call it as aB.setA(this) in foo(). Suppose we had:
class IntermediateConcreteA extends AbstractA<ConcreteB> {
#Override
public ConcreteB createB() {
return new ConcreteB();
}
}
class SubConcreteA1 extends IntermediateConcreteA {}
class SubConcreteA2 extends IntermediateConcreteA {}
class ConcreteB extends AbstractB<SubConcreteA2> {}
Now if I have a SubConcreteA1 and call its foo(), then createB() will return an object that can pass as an AbstractB<SubConcreteA2> but cannot pass as an AbstractB<SubConcreteA1>. Therefore its setA() shouldn’t accept this as an argument. The compiler error message is logical after all.
Each abstract class would be parameterized with two type parameters, one for the actual concrete class of A, and one for the actual concrete class of B:
public abstract class AbstractA<A extends AbstractA<A,B>, B extends AbstractB<A,B>> {
protected void foo() {
B aB = createB();
aB.setA(getThis());
}
abstract public A getThis();
abstract public B createB();
}
public abstract class AbstractB<A extends AbstractA<A,B>, B extends AbstractB<A,B>> {
private A theA;
public void setA(A theA) {
this.theA = theA;
}
protected A getA() {
return theA;
}
}
public class ConcreteA extends AbstractA<ConcreteA, ConcreteB> {
#Override
public ConcreteA getThis() {
return this;
}
#Override
public ConcreteB createB() {
return new ConcreteB();
}
public void concreteAMethod() {
// ...
}
}
public class ConcreteB extends AbstractB<ConcreteA, ConcreteB> {
public void bar() {
ConcreteA a = getA();
a.concreteAMethod();
}
}
A factory can solve it:
public abstract class AbstractA {
public void abstractAMethod() {
// ...
}
}
public abstract class AbstractB<A> {
private A theA;
public void setA(A theA) {
this.theA = theA;
}
protected A getA() {
return theA;
}
}
public abstract class AbstractFactory<A extends AbstractA, B extends AbstractB<A>> {
private A theA = createA();
public A getA() {
return theA ;
}
public B getNextB() {
B newB = createB();
newB.setA(theA);
return newB;
}
protected abstract A createA();
protected abstract B createB();
}
Now the user can go:
public class ConcreteA extends AbstractA {
public void concreteAMethod() {
// ...
}
}
public class ConcreteB extends AbstractB<ConcreteA> {
public void bar() {
ConcreteA a = getA();
a.abstractAMethod();
a.concreteAMethod();
}
}
public class ConcreteFactory extends AbstractFactory<ConcreteA, ConcreteB> {
#Override
protected ConcreteA createA() {
return new ConcreteA();
}
#Override
protected ConcreteB createB() {
return new ConcreteB();
}
}
I don’t think it’s a typical application of the abstract factory pattern, though …
#Chris Wohlert, I did give up in my production code since I considered the factory overkill, but I could not let go of the theoretical question.
I have come to realize that my problem really came out of stuffing two concepts into the AbstractA/ConcreteA hierarchy that didn’t belong together. Though maybe not interesting to very many, I am posting this insight for two reasons: (1) I feel I owe Chris Wohlert the answer I have found myself (2) more importantly, I’d love to inspire anyone else facing a similar tricky generics issue to review your design from a higher level than just solving the generics and/or class cast issue. It certainly helped me. The cast/generics problem was a sign that something more fundamental was not quite right.
public abstract class AbstractA {
public void foo() {
AbstractB aB = createB();
aB.setA(this);
}
/** factory method */
abstract public AbstractB createB();
}
public abstract class AbstractB {
private AbstractA theA;
public void setA(AbstractA theA) {
this.theA = theA;
}
// methods that use theA
}
No generics and no class cast. Taking out the stuff that didn’t belong in the A class hierarchy into ConcreteC (with no AbstractC):
public class Client {
public void putTheActTogether() {
ConcreteC theC = new ConcreteC();
// the concrete A
AbstractA theA = new AbstractA() {
#Override
public AbstractB createB() {
return new ConcreteB(theC);
}
};
// call methods in theA
}
}
public class ConcreteB extends AbstractB {
private final ConcreteC c;
public ConcreteB(ConcreteC c) {
super();
this.c = c;
}
public void bar() {
c.concreteCMethod();
}
}
public class ConcreteC {
public void concreteCMethod() { // was concreteAMethod(); moved and renamed
// ...
}
}
The client needs a few more lines than before. In my real-world code I needed to duplicate one final field in AbstractA and ConcreteC, but it made sense to do. All in all I consider it a low price for a design that is otherwise pure and simple.
I know that multiple inheritances between Interfaces is possible, e.g.:
public interface C extends A,B {...} //Where A, B and C are Interfaces
But is it possible to have a regular Class inherit from multiple Interfaces like this:
public class A implements C,D {...} //Where A is a Class and C and D are interfaces
A Java class can only extend one parent class. Multiple inheritance (extends) is not allowed. Interfaces are not classes, however, and a class can implement more than one interface.
The parent interfaces are declared in a comma-separated list, after the implements keyword.
In conclusion, yes, it is possible to do:
public class A implements C,D {...}
In a word - yes.
Actually, many classes in the JDK implement multiple interfaces. E.g., ArrayList implements List, RandomAccess, Cloneable, and Serializable.
public class A implements C,D {...} valid
this is the way to implement multiple inheritence in java
Yes, a class can implement multiple interfaces. Each interface provides contract for some sort of behavior. I am attaching a detailed class diagram and shell interfaces and classes.
Ceremonial example:
public interface Mammal {
void move();
boolean possessIntelligence();
}
public interface Animal extends Mammal {
void liveInJungle();
}
public interface Human extends Mammal, TwoLeggedMammal, Omnivore, Hunter {
void liveInCivilization();
}
public interface Carnivore {
void eatMeat();
}
public interface Herbivore {
void eatPlant();
}
public interface Omnivore extends Carnivore, Herbivore {
void eatBothMeatAndPlant();
}
public interface FourLeggedMammal {
void moveWithFourLegs();
}
public interface TwoLeggedMammal {
void moveWithTwoLegs();
}
public interface Hunter {
void huntForFood();
}
public class Kangaroo implements Animal, Herbivore, TwoLeggedMammal {
#Override
public void liveInJungle() {
System.out.println("I live in Outback country");
}
#Override
public void move() {
moveWithTwoLegs();
}
#Override
public void moveWithTwoLegs() {
System.out.println("I like to jump");
}
#Override
public void eat() {
eatPlant();
}
#Override
public void eatPlant() {
System.out.println("I like this grass");
}
#Override
public boolean possessIntelligence() {
return false;
}
}
public class Lion implements Animal, FourLeggedMammal, Hunter, Carnivore {
#Override
public void liveInJungle() {
System.out.println("I am king of the jungle!");
}
#Override
public void move() {
moveWithFourLegs();
}
#Override
public void moveWithFourLegs() {
System.out.println("I like to run sometimes.");
}
#Override
public void eat() {
eatMeat();
}
#Override
public void eatMeat() {
System.out.println("I like deer meat");
}
#Override
public boolean possessIntelligence() {
return false;
}
#Override
public void huntForFood() {
System.out.println("My females hunt often");
}
}
public class Teacher implements Human {
#Override
public void liveInCivilization() {
System.out.println("I live in an apartment");
}
#Override
public void moveWithTwoLegs() {
System.out.println("I wear shoes and walk with two legs one in front of the other");
}
#Override
public void move() {
moveWithTwoLegs();
}
#Override
public boolean possessIntelligence() {
return true;
}
#Override
public void huntForFood() {
System.out.println("My ancestors used to but now I mostly rely on cattle");
}
#Override
public void eat() {
eatBothMeatAndPlant();
}
#Override
public void eatBothMeatAndPlant() {
eatPlant();
eatMeat();
}
#Override
public void eatMeat() {
System.out.println("I like this bacon");
}
#Override
public void eatPlant() {
System.out.println("I like this broccoli");
}
}
Of course... Almost all classes implements several interfaces. On any page of java documentation on Oracle you have a subsection named "All implemented interfaces".
Here an example of the Date class.
It is true that a java class can implement multiple interfaces at the same time, but there is a catch here.
If in a class, you are trying to implement two java interfaces, which contains methods with same signature but diffrent return type, in that case you will get compilation error.
interface One
{
int m1();
}
interface Two
{
float m1();
}
public class MyClass implements One, Two{
int m1() {}
float m1() {}
public static void main(String... args) {
}
}
output :
prog.java:14: error: method m1() is already defined in class MyClass
public float m1() {}
^
prog.java:11: error: MyClass is not abstract and does not override abstract method m1() in Two
public class MyClass implements One, Two{
^
prog.java:13: error: m1() in MyClass cannot implement m1() in Two
public int m1() {}
^
return type int is not compatible with float
3 errors
Yes, it is possible. This is the catch: java does not support multiple inheritance, i.e. class cannot extend more than one class. However class can implement multiple interfaces.
An interface can extend other interfaces. Also an interface cannot implement any other interface.
When it comes to a class, it can extend one other class and implement any number of interfaces.
class A extends B implements C,D{...}
I have this Java Interface:
public interface Box {
public void open();
public void close();
}
This interface is extended by this class:
public class RedBox implements Box {
public void open() {
}
public void close() {
}
}
The problems is that I'm looking to add other classes in the future that will also implement the Box Interface. Those new classes will have their own methods, for example one of the classes will have a putInBox() method, But if I add the putInBox() method to the Box Interface, I will also be forced to add an empty implementation of putInBox() method to the previous classes that implemented the Box Interface like the RedBox class above.
I'm adding putInBox() to the Box Interface because there is a class Caller that takes an object of classes that implemented the Box Interface, example:
public class Caller {
private Box box;
private int command;
public Caller(Box b) {
this.box = b;
}
public void setCommandID(int id) {
this.command = id;
}
public void call() {
if(command == 1) {
box.open();
}
if(command == 2) {
box.close();
}
// more commands here...
}
}
Caller c = new Caller(new RedBox());
c.call();
How do I implement the Box Interface in the new classes without been forced to add empty implementation of new methods to each of the previous classes that implemented the Box Interface.
You are not limited to a single interface - you can build an entire hierarchy! For example, you can make these three interfaces:
public interface Box {
public void open();
public void close();
}
public interface LockableBox extends Box {
public void lock();
public void unlock();
}
public interface MutableBox extends Box {
public void putItem(int item);
public void removeItem(int item);
}
Now your boxes can implement an interface from the hierarchy that fits your design.
public class RedBox implements LockableBox {
public void open() {}
public void close() {}
public void lock() {}
public void unlock() {}
}
public class BlueBox implements MutableBox {
public void open() {}
public void close() {}
public void putItem(int item) {}
public void removeItem(int item) {}
}
With a hierarchy in place, you can continue programming to the interface:
MutableBox mb = new BlueBox();
mb.putItem(123);
LockableBox lb = new RedBox();
lb.unlock();
The new classes implementing the Box interface will only need to implement the methods in the Box interface, not any other methods in other classes implementing the Box interface.
As said above, there's no need to have a new method in a new class added to the Box interface itself, you can just leave it in that new class, and so it won't interfere with any other implementation.
But if you do want to have new methods at the interface level, a way to introduce some flexibility is to use an (abstract) base implementation of your interface that provides (empty) implementations of all methods:
public abstract class BoxBase implements Box {
public void open() { }
public void close() { }
}
public class RedBox extends BoxBase {
#Override
public void open() {
// open a red box
}
}
This way, when adding new methods to your Box interface, you will only need to add an implementation of the method to the BoxBase class, and it won't interfere with your RedBox class.