Java cooperating generic classes: can we avoid unchecked cast? - java

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.

Related

Optional overloaded methods when overriding

Case :
I have an abstract class A. It contains two methods
abstract void search(Position p);
abstract void search(Animal a);
Class B and C extends A. I would like class B to implement search(Position p) only and class C to implement search(Animal a) only. However when I do so it gives an error, telling me to implement both of the method overloads.
How could I solve the problem? Any help is greatly appreciated
Here are the rules for classes extending Abstract class
First concrete/non-abstract class must implement all methods
If abstract class extends Abstract class, it can but need not implement
abstract methods.
Option 1: Interface Segregation
separate search(XXX) into two abstract classes
Option 2: Generics. Make search a Generic Type
public abstract class ClassA {
public abstract <T> void search(T t);
public static void main(String ...args){
ClassA classA = new ClassB();
classA.search(new Animal());
}
}
class Animal{
}
class ClassB extends ClassA {
#Override
public <Animal> void search(Animal t) {
System.out.println("called");
}
}
Option 3: Interface
public class ClassA {
public static void main(String... args) {
Searchable classA = new ClassB();
classA.search(new Animal());
}
}
interface Searchable {
public <T> void search(T t);
}
class Animal {
}
class ClassB implements Searchable {
#Override
public <Animal> void search(Animal t) {
System.out.println("called");
}
}
Option 4: Throw UnsupportedOperationException Exception(Not recomended)
class ClassB extends ClassA {
#Override
void search(Position p) {
throw new UnsupportedOperationException("Not Supported");
}
#Override
void search(Animal a) {
}
}

Dynamically cast classes

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.

How to use more implementations of one interface in one class?

I would like to ask for your help regarding the following problem.
There is an interface which has more implementations:
public interface MyInterface {
void method();
}
public class MyInterfaceA implements MyInterface
public class MyInterfaceB implements MyInterface
and there is a class which uses these implementations of the interface in its different methods:
public class MyClass {
public void firstMethod() {
new MyInterfaceA().method();
}
public void secondMethod() {
new MyInterfaceB().method();
}
}
My problem is that I wouldn't like to create new specific instances in the methods of the class, so somehow I would like to hide which implementation is used.
Do you know a nice solution for this? Is there any design pattern what I can use? How can I hide the concrete implementations or I cannot?
Thanks for your answers in advance!
For example, you can receive the implementations in the constructor of MyClass and further use it. It helps you to hide the specific implementations.
public class MyClass {
private MyInterface one;
private MyInterface two;
private MyClass(MyInterface one, MyInterface two) {
this.one = one;
this.two = two;
}
public void firstMethod() {
one.method();
}
public void secondMethod() {
two.method();
}
}
You can apply the Factory pattern:
class Factory {
public MyInterface a() { return new MyInterfaceA(); }
public MyInterface b() { return new MyInterfaceB(); }
}
public class MyClass {
private Factory factory;
public MyClass(Factory factory) { this.factory = factory; }
public void firstMethod() {
factory.a().method();
}
public void secondMethod() {
factory.b().method();
}
}
Inside the Factory class you can cache the objects created if necessary.

Any way to specify a java generic type variable that extends any one of multiple classes?

So suppose I have 2 classes:
public class A
{
public void
f()
{
}
}
public class B
{
public void
f()
{
}
}
I would like to write a generic static method that could call f when passed an instance of A or B. I tried:
public class C
{
public static <T extends A & B> void
g(T t)
{
t.f();
}
public static void main(String[] args)
{
A a = new A();
g(a);
}
}
But the compiler claims A is not a valid substitute for "T extends A & B", which I assume is because T must extend BOTH A and B, which obviously A does not. I could not find a way to specify something like "T extends A OR B". Is something like this not achievable? I am a java neophyte, so any help with this would be appreciated.
You can only specify one generic type. Use interfaces instead.
An interface specifies a certain set of methods, each member of it has to have. A class can implement multiple interfaces.
In your example, I would define an interface with the method f():
public interface MyInterface {
void f();
}
Let A and B implement the interface:
public class A implements MyInterface
{
#Override
public void f() {
// ...
}
}
public class B implements MyInterface
{
#Override
public void f() {
// ...
}
}
Then you can just specify the interface as type of the argument for your method:
public static void g(MyInterface obj)
{
obj.f();
}
For more detail on interfaces, check the Java documentation: What Is an Interface?

Inheriting from two classes with Java?

I have made a class to include a custom title bar with my apps logo on it. This works well except that for the majority of my classes I need to be able to inherit that functionality as well as that of say a ListActivity. What to do?
Any help appreciated.
you should favor composition (and delegation) over inheritance :
public interface FirstClassInterface {
void method1();
}
public interface SecondClassInterface {
void method2();
}
public class FirstClass implements FirstClassInterface {
// ...
}
public class SecondClass implements SecondClassInterface {
// ...
}
public class FirstAndSecondClass implements FirstClassInterface , SecondClassInterface
{
private FirstClassInterface firstclass;
private SecondClassInterface secondclass;
public FirstAndSecondClass(FirstClassInterface firstclassinterface, SecondClassInterface secondclassinterface) {
this.firstclass= firstclassinterface;
this.secondclass= secondclassinterface;
}
public void method1() {
this.firstclass.method1();
}
public void method2() {
this.secondclass.method2();
}
public static void main(String[] args) {
FirstAndSecondClass t = new FirstAndSecondClass(new FirstClass(), new SecondClass());
t.method1();
t.method2();
}
}
In Java, you cannot have:
class MyClass extends ClassA, ClassB { ... }
Depending on what you are doing, it might be possible to use:
class ClassB extends ClassA { ... }
class MyClass extends ClassB { ... }

Categories

Resources