How can I use interface with generics? - java

This is my structure.
public class FooInfo { ... }
public class FooAInfo extends FooInfo { ... }
public class FooBInfo extends FooInfo { ... }
public interface IFoo<T1 extends FooInfo> {
void proc(T1 fooInfo);
}
public class FooA implements IFoo<FooAInfo> {
void proc(FooAInfo fooInfo) { ... }
}
public class FooB implements IFoo<FooBInfo> {
void proc(FooBInfo fooInfo) { ... }
}
And I want to use them like
public abstract class FooUser {
protected IFoo<FooInfo> foo;
}
public class FooAUser extends FooUser {
public FooAUser() {
super.foo = new FooA();
}
}
public class FooBUser extends FooUser {
public FooBUser() {
super.foo = new FooB();
}
}
I want to initialize FooUser's foo variable in FooAUser and FooBUser child class.
But It doesn't work because new FooA() and new FooB() don't have <FooInfo>.
What should I do?

You just need to make FooUser generic:
public abstract class FooUser<T extends FooInfo> {
protected IFoo<T> foo;
}
public class FooAUser extends FooUser<FooAInfo> {
public FooAUser() {
super.foo = new FooA();
}
}
public class FooBUser extends FooUser<FooBInfo> {
public FooBUser() {
super.foo = new FooB();
}
}
Alternatively, you can use a generic wildcard (?) on your foo parameter:
public abstract class FooUser {
protected IFoo<?> foo;
}
public class FooAUser extends FooUser {
public FooAUser() {
super.foo = new FooA();
}
}
public class FooBUser extends FooUser {
public FooBUser() {
super.foo = new FooB();
}
}
(Unrelated to the question, but your proc() methods in your classes also need to be declared public.)

Related

Java return ArrayList<MyObject> in medhot which returns an ArrayList of an Interface

I have two classes which have to getMethodes which returns an ArrayList of two Objects which implements a interface
public class MyClass1 implements IMyClasses<MyObject1>{
public ArrayList<MyObject1> getMyObject() { ... }
}
public class MyClass2 implements IMyClasses<MyObject1>{
public ArrayList<MyObject1> getMyObject() { ... }
}
MyObject1 and MyObject2 implements IMyObject
In my ManagerClass I would like to implement a function which can return any IMyObject implementation
ArrayList<IMyObject) get() {
if (...) {
return new MyClass1().getMyObject();
} else {
return new MyClass2().getMyObject();
}
}
Before I have introduced the Generic typ on MyClass1 and MyClass2 it worked fine, but with the Generic which I need to get the proper object if needed, I'm not able to return the object which has as return type the Interface?
Some help?
Edit this is a full working example, the trick is to do <? extend IMyObject> thx to #Alexander.Furer
public class ManagerClassTest {
public interface IManagerClass {
public ArrayList<? extends IMyObject> getMyObject(boolean myObject1);
}
public interface IMyClass<I>{
public ArrayList<I> getMyObject();
}
public interface IMyObject {}
public class MyObject1 implements IMyObject {}
public class MyClass1 implements IMyClass<MyObject1> {
#Override
public ArrayList<MyObject1> getMyObject() {
return new ArrayList<MyObject1>();
}
}
public class MyObject2 implements IMyObject {}
public class MyClass2 implements IMyClass<MyObject2> {
#Override
public ArrayList<MyObject2> getMyObject() {
return new ArrayList<MyObject2>();
}
}
public class ManagerClass implements IManagerClass {
private ArrayList<MyObject1> getMyObject1() {
return new MyClass1().getMyObject();
}
private ArrayList<MyObject2> getMyObject2() {
return new MyClass2().getMyObject();
}
#Override
public ArrayList<? extends IMyObject> getMyObject(boolean myObject1) {
if (myObject1) {
return new MyClass1().getMyObject();
} else {
return new MyClass2().getMyObject();
}
}
}
}
ArrayList<MyObject1> is not of type ArrayList<IMyObject> ,BTW, you have a typo :ArrayList<IMyObject)
Declare the get method of ManagerClass as :
ArrayList<? extends IMyObject> get() {
}

How to use a parameter of type `Derived` in a overridden method accepting `Base`?

I have the following situation:
abstract class Base {
int data = 0;
void baseMethod() {
System.out.println("baseMethod:" + data);
}
}
class DerivedA extends Base {
void DerivedBMethodA() {
}
void usefulMethod(Something something) {
something.doSomething(this);
}
interface Something {
void doSomething(DerivedA deriv);
}
}
class DerivedB extends Base {
void DerivedMethodB() {
}
}
public class Temp {
public static void main() {
DerivedA a = new DerivedA();
a.usefulMethod(new DerivedA.Something() {
#Override
public void doSomething(DerivedA deriv) {
deriv.DerivedBMethodA();
}
});
}
}
I want to push usefulMethod and Something upto the Base class so that DerivedB can leverage it. And I want implementations of Something.doSomething to be able to use a derived type, so that it can access derived functionality.
How do I do that?
Attempts
I've tried the following:
abstract class Base {
int data = 0;
void baseMethod() {
System.out.println("baseMethod:" + data);
}
void usefulMethod(Something something) {
something.doSomething(this);
}
interface Something {
void doSomething(Base deriv);
}
}
class DerivedA extends Base {
void DerivedBMethodA() {
}
}
class DerivedB extends Base {
void DerivedMethodB() {
}
}
public class Temp {
public static void main() {
DerivedA a = new DerivedA();
a.usefulMethod(new Base.Something() {
#Override
public void doSomething(DerivedA deriv) {
deriv.DerivedBMethodA();
}
});
}
}
but that fails as my anonymous Something doesn't implement doSomething(Base). So trying to use generics:
I tried:
interface Something {
void doSomething(<? extends Base> deriv);
}
but that won't compile due to: "Wildcards may be used only as reference parameters"
I tried:
interface Something {
<T extends Base> void doSomething(T deriv);
}
but that requires me to implement the interface as so:
a.usefulMethod(new Base.Something() {
#Override
public <T extends Base> void doSomething(T deriv) {
}
});
which obviously doesn't allow me access to the derived type?
There are ways I can make it "work" but they're undesirable:
This:
interface Something {
void doSomething(Base deriv);
}
a.usefulMethod(new Base.Something() {
#Override
public void doSomething(Base deriv) {
DerivedA a1 = (DerivedA) deriv;
a1.DerivedBMethodA();
}
});
But that requires me to cast in each implementation, which seems wasteful.
And this:
package com.miurasample.ui.info;
abstract class Base {
int data = 0;
void baseMethod() {
System.out.println("baseMethod:" + data);
}
void usefulMethod(Something something) {
something.doSomething(this);
}
interface Something<T extends Base> {
void doSomething(T deriv);
}
}
public class Temp {
public static void main() {
DerivedA a = new DerivedA();
a.usefulMethod(new Base.Something<DerivedA>() {
#Override
public void doSomething(DerivedA deriv) {
}
});
}
}
but that results in a warning/IDE highlight in usefulMethod of:
"Unchecked call to doSomething(T) as a member of raw type Base.Something"
What's the tersest and "cleanest" way to do this? Is that I'm doing even sane?
It is difficult to say if your design is wrong or not. We dont have full scope of your requirements to assert that, but here is clean non cast approach to what you are trying to do. It does require extra method in your derived classes:
public static void main(String... args) {
DerivedA a = new DerivedA();
a.usefulMethod( new Base.Something<DerivedA>() {
#Override
public void doSomething(DerivedA deriv) {
deriv.DerivedBMethodA();
}
} );
}
public abstract static class Base< T extends Base<T> > {
int data = 0;
protected abstract T getThis();
void baseMethod() {
System.out.println("baseMethod:" + data);
}
void usefulMethod(Something<T> something) {
something.doSomething( getThis() );
}
interface Something< T extends Base<T> > {
void doSomething(T deriv);
}
}
public static class DerivedA extends Base<DerivedA> {
protected DerivedA getThis(){
return this;
}
void DerivedBMethodA() {}
}
public static class DerivedB extends Base<DerivedB> {
protected DerivedB getThis(){
return this;
}
void DerivedMethodB() {}
}

Nested extends in generics

I have three classes:
class ClassR {}
class ClassA<T extends ClassR>{}
class ClassB<E extends ClassA<T extends ClassR>> extends ClassA<T> {
void foo(T param) {
}
void bar(E param) {
}
}
The third class does not compile unless I change it to
class ClassB<E extends ClassA<T>, T extends ClassR> extends ClassA<T> {
void foo(T bar) {
}
void bar(E param) {
}
}
Is there a way to keep only E parameter I need to pass when creating ClassB, and T being inferred? For example, it would be convenient to use:
new ClassB<ClassA<ClassR>>()
instead of:
new ClassB<ClassA<ClassR>, ClassR>()
This even simpler approach might work for you:
class ClassR {}
class ClassA<T extends ClassR>{}
class ClassB<T extends ClassR> extends ClassA<T> {
void foo(T bar) {
}
void bar(ClassA<T> param) {
}
}
And usage then bypasses any reference to ClassA to become:
class SubR extends ClassR {}
ClassB<SubR> obj = new ClassB<SubR>();
Not sure if this is the answer you want but surely the simplest version reads:
class ClassR {
}
class ClassA<T extends ClassR> {
}
class ClassB<T extends ClassR> extends ClassA<T> {
void foo(T bar) {
}
}
public void test() {
ClassB<ClassR> classB = new ClassB<>();
}
As type E extends ClassA you can safely omit the ClassA type parameter in its declaration.Proper ClassA type parameter is enforced in the second parameter to ClassB. See below code for illustration :
class ClassB<E extends ClassA, T extends ClassR> extends ClassA<T> {
private ClassA ob;
public ClassB(E e, T t) {
super(t);
ob = e;
}
}
Usage sample:
class ClassR {
public ClassR() {};
}
class ClassS extends ClassR {
private int x;
public ClassS(int x) {
super();
this.x = x;
}
}
public static void test() {
ClassS data1 = new ClassS(1);
ClassB <ClassB, ClassS> first = new ClassB<>(null, data1);
ClassS data2 = new ClassS(2);
ClassB <ClassB, ClassS> second = new ClassB<>(first, data2);
}

Instantiating generic class and implementing generic interface

I have this class:
public DrawItem {
protected String getSeperator() {
return "";
}
.......
// some other methods
}
I've another class which extends DrawItem.
public DrawNumber extends DrawItem {
#Override
protected String getSeperator() {
return "-";
}
}
Now, in a generic class CombinationGenerator<E>, I'm trying to instantiate objects of DrawItem/DrawNumber. As instantiating a generic type is not possible in java (like new E(...)), I've created a Factory interface according to this answer.
public interface DrawItemFactory<E> {
E create(...);
}
Then in the CombinationGenerator<E> class,
public class CombinationGenerator<E> {
DrawItemFactory<E> factory;
public CombinationGenerator<E>(DrawItemFactory<E> factory) {
this.factory = factory;
}
public List<E> generate() {
......
list.add(factory.create(...));
......
}
}
And now the DrawNumber class implements DrawItemFactory<DrawItem> interface.
public DrawItem implements DrawItemFactory<DrawItem> {
protected String getSeperator() {
return "";
}
#Override
public DrawItem create(...) {
return new DrawItem(...);
}
.......
// some other methods
}
And I can create CombinationGenerator<DrawItem> class.
DrawItem drawItem = new DrawItem(...);
CombinationGenerator<DrawItem> generator = new CombinationGenerator<DrawItem>(drawItem);
List<DrawItem> combinations = generator.generate();
So far, everything is fine. But when I try to create a DrawNumber class like this,
public DrawNumber implements DrawItemFactory<DrawNumber> {
....
}
It gives me the following error:
The interface DrawItemFactory cannot be implemented more than once with different arguments: DrawItemFactory<DrawItem> and DrawItemFactory<DrawNumber>
I've tried this solution but I got the same error. Is there any other way to do this?
Instead of using all those factories you could do something like this:
public class CombinationGenerator<E> {
E instance;
public CombinationGenerator(Class<E> clazz) {
Constructor<?> con = clazz.getConstructor();
this.instance = (E) con.newInstance();
}
}
...
CombinationGenerator<DrawNumber> cg = new CombinationGenerator<DrawNumber>(DrawNumber.class);
According to #JB Nizet's comment, I've solved the problem by creating two separate factory classes like this:
public interface ItemFactory<E> {
E create(int[] values);
public static class DrawItemFactory implements ItemFactory<DrawItem> {
#Override
public DrawItem create(int[] values) {
return new DrawItem(values);
}
}
public static class DrawNumberFactory implements ItemFactory<DrawNumber> {
#Override
public DrawNumber create(int[] values) {
return new DrawNumber(values);
}
}
}
In the CombinationGenerator,
public class CombinationGenerator<E> {
ItemFactory<E> factory;
public CombinationGenerator<E>(ItemFactory<E> factory) {
this.factory = factory;
}
public List<E> generate() {
......
list.add(factory.create(...));
......
}
}
And instantiated CombinationGenerator like this:
DrawNumber drawNumber = new DrawNumber();
CombinationGenerator<DrawNumber> generator = new CombinationGenerator<DrawNumber>(new ItemFactory.DrawNumberFactory());
List<DrawNumber> combinations = generator.generate();

How to return generic type in a method interface

How to define a generic return type for an interface, so that it's implementing class can have a return type of its own?
public interface A {
public <T> T doSomething();
}
public class ImplA implements A {
public SomethingElseA doSomething() {
return obj.doSomething();
}
}
public class ImplB implements A {
public SomethingElseB doSomething() {
return obj.doSomething();
}
}
Try something as follows.
interface A<T> {
T doSomething();
}
class ImplA implements A<SomethingElseA> {
public SomethingElseA doSomething() {
...
}
}
class ImplB implements A<SomethingElseB> {
public SomethingElseB doSomething() {
...
}
}
I'm guessing you mean like this? I changed do() to foo() as do is a reserved word...
public interface A<T> {
public T foo();
}
public class ImplA implements A<SomethingElseA> {
#Override
public SomethingElseA foo() {
return obj.doSomething();
}
}
public class ImplB implements A<SomethingElseB> {
#Override
public SomethingElseB foo() {
return obj.doSomething();
}
}

Categories

Resources