Nested extends in generics - java

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);
}

Related

How can I use interface with generics?

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.)

Java - How to call method class with interface without know class name

I'm new in java, I want to call method class from implemented Class with interface without know class name "ClassA", which only know Object c and I have 2 file.
File (1) CobaInterface.java
package cobainterface;
public class CobaInterface {
public static void main(String[] args) {
ImplementedClass implementedClass = new ImplementedClass();
ClassA clsA = new ClassA();
implementedClass.myMethodFromClassA(clsA);
}
}
class ClassA{
public Integer getTwo(){
return 2;
}
}
interface MyInterface {
public void myMethod();
//here interface
public void myMethodFromClassA(Object c);
}
File (2) : ImpementedClass.java
package cobainterface;
public class ImplementedClass extends CobaInterface {
public void myMethodFromClassA(Object c) {
//System.out.println(c.getTwo()); <- wrong when call method c.getTwo()
}
}
How about if I want to call method getTwo() from ClassA without know Class Name, which only know Object c from file (2) as describe in code above. Thanks for advance.
You should use generic types so the implementation knows what the object will be,
interface MyInterface<T> {
public void myMethod();
//here interface
public void myMethodFromClassA(T c);
}
The impl becomes,
package cobainterface;
public class ImplementedClass Implements MyInterface<ClassA> {
public void myMethodFromClassA(ClassA c) {
//System.out.println(c.getTwo()); <- wrong when call method c.getTwo()
}
}
All together,
class Scratch {
public static void main(String[] args) {
ImplementedClass implementedClass = new ImplementedClass();
ClassA clsA = new ClassA();
implementedClass.myMethodFromClassA(clsA);
}
}
class ImplementedClass implements MyInterface<ClassA> {
#Override
public void myMethod() {
}
#Override
public void myMethodFromClassA(ClassA c) {
System.out.println(c.getTwo());
}
}
class ClassA {
public Integer getTwo() {
return 2;
}
}
interface MyInterface<T> {
void myMethod();
void myMethodFromClassA(T c);
}
You could also do a cast
System.out.println((MyClass)c.getTwo());
but you will lose all benefit of type saftey.

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() {
}

Avoid cast in a generics hierarchy

I have some difficulty to simplify more the problem. Sorry if they are too many code here.
I try to improve the architecture of the code above because I hate warning and cast and I feel something wrong.
Now, the code.
I have a util class with these two parametrized methods (same signature as OpenJPA's CriteriaBuilder...)
public class MyUtil {
public void equal(List<?> l, Object value) {
// do something (see CriteriaBuilder.equal method)
}
public <Y extends Comparable<? super Y>> void greaterThan(List<? extends Y> l, Y value) {
// do something (see CriteriaBuilder.greaterThan method)
}
}
Then, I want to be able to abstract them to call it via an interface.
public interface IOperation<T> {
// maybe make this method generic ? but how ?
public abstract void doOp(List<T> l, T value);
}
public abstract class AbstractOperation<T> implements IOperation<T> {
protected MyUtil myUtil;
}
public class EqualOp extends AbstractOperation<Object> {
#Override
public void doOp(List<Object> path, Object value) {
myUtil.equal(path, value);
}
}
public class GreaterThanOp<T extends Comparable<? super T>> extends AbstractOperation<T> {
#Override
public void doOp(List<T> path, T value) {
myUtil.greaterThan(path, value);
}
}
I create a factory
public class OperationFactory {
private static OperationFactory instance;
public static OperationFactory getInstance() {...}
public IOperation<?> get(String op) {
if ("=".equals(op)) {
return new EqualOp();
} else if (">".equals(op)) {
return new GreaterThanOp<Comparable<? super Object>>();
}
throw new InvalidParameterException();
}
}
Then I use it :
public class Client {
public void needOp(String op) {
IOperation<String> operation = (IOperation<String>) OperationFactory.getInstance().get(op); // How to avoid this cast ?
List<String> l = null;
operation.doOp(l, "a string");
}
}
My question is : is it possible to avoid this cast in the Client class ? How ? Is there a way to have a better architecture ?
Thanks for reading
I'm assuming you can require your type to be Comparable.
Parameterize EqualOp like GreaterThanOp:
public class EqualOp<T extends Comparable<T>> extends AbstractOperation<T> {
#Override public void doOp(List<T> path, T value) ...
And define get() like this:
public <T extends Comparable<T>> IOperation<T> get(String op) {
if ("=".equals(op)) {
return new EqualOp<T>();
} else if (">".equals(op)) {
return new GreaterThanOp<T>();
}
...

Define abstract class method argument Enum<E> for multiple values

I have a question.
How I can define an Enum type for multiple static classes with a different object as Enum?
Example:
public abstract class AbstractClass
{
public Enum<?> AbstractMethod();
}
public class StaticClass extends AbstractClass
{
public enum en
{
FOO3,
FOO4
}
#Override
public Enum<en>[] AbstractMethod()
{
return en.values();
}
}
public class StaticClass2 extends AbstractClass
{
public enum en
{
FOO1,
FOO2
}
#Override
public Enum<en>[] AbstractMethod()
{
return en.values();
}
}
But that code throws an error:
The method public boolean AbstractMethod(Enum<ObjectX> en1) dosn't exsist in AbstractClass (X is the Number of the Object)
Doing this it works but throws RawTypes warning:
public abstract class AbstractClass
{
public Enum[] AbstractMethod();
}
public class StaticClass extends AbstractClass
{
public enum en
{
FOO3,
FOO4
}
#Override
public Enum[] AbstractMethod()
{
return en.values();
}
}
public class StaticClass2 extends AbstractClass
{
public enum en
{
FOO1,
FOO2
}
#Override
public Enum[] AbstractMethod()
{
return en.values();
}
}
Is this what you mean?
Enum:
public enum Fruits {
APPLE, ORANGE;
}
Classes:
public static abstract class Parent {
public abstract <E extends Enum<?>> void printEnum(final E e);
}
public static class Child extends Parent {
#Override
public <E extends Enum<?>> void printEnum(final E e) {
System.out.println(e.name());
}
}
Usage:
new Child().printEnum(Fruits.ORANGE); // Prints ORANGE

Categories

Resources