Java factory inheritance with generic interface implementation - java

I would like to have a factory that inherits another one with both factories implementing same generic interface with different type that inherits one another:
class FactoryA implements FactoryI<A> {
// common code
...
A get() {
return new A();
}
}
class FactoryB extends FactoryA implements FactoryI<B> {
B get() {
return new B();
}
}
class B extends A {
}
FactoryI<T> {
T get()
}
But this gives me following compilation error:
'FactoryI' cannot be inherited with different type arguments: 'A' and 'B'
My first version did not have FactoryB inheriting from FactoryA and this was working fine.
But it turns out that there is now common code between both factories that I want to reuse.
What is the best way to achieve this?

You need to make FactoryA generic as well. This way a subclass can return a different subclass of A
class FactoryA<T extends A> implements FactoryI<T> {
// common code
public T get() {
return (T) new A();
}
}
class FactoryB extends FactoryA<B> {
public B get() {
return new B();
}
}
class A {
}
class B extends A {
}
interface FactoryI<T> {
T get();
}

Related

passing Object Instances as generics to a method

I have a scenario similar to the below example.
I have two different objects and have already created instances from them. I need to pass these instances as generic to a method parameters.
I tried passing the method parameters as Class obj but it didnt work
Class A
{
A()
{
List<String>collection = new ArrayList<>();
}
}
Class B
{
B()
{
List<String>collection = new ArrayList<>();
}
}
Class Main()
{
A a = new A();
B b = new B();
methodTest(a);
methodTest(b);
void methodTest(Class<T> genericObj)
{
genericObj.collection.add("1");
// I need to pass both the instance A and instance B to
genericObj
}
}
Need some suggestions.
You don't pass generics to methods, since generic is a Type, not an object.
What you do is, you pass an object; with generic being declared in your class.
E.g.
public class Test <T extends ClasThatHasCollection> {
void methodTest(T genericObj) {
genericObj.collection.add("1");
}
}
However in your case, generics seem like an overkill!
Just have a parent class P that has .collection instance variable; and have both classes A and B extend P; and pass object type P into methodTest:
public class P {
public Collection collection;
// ....
}
public class A extends P {
}
void methodTest(P genericObj) {
P.collection.add("1");
}
The simplest way would be to create a base class and have A and B inherit from it.
In the method you use the base class as the type.
This is valid since both A and B extend it.
For example:
class Base {
List<String> collection;
Base() {
collection = new ArrayList<>();
}
}
class A extends Base{
A(){
super()
}
}
class B extend Base{
B(){
super()
}
}
void methodTest(Base genericObj)
{
genericObj.collection.add("1");
}
Another possibility is to use an interface. This would be useful if the collections are not the same type and are therefore not defined in the base object.
Using an interface:
interface MyInterface{
public ArrayList<> getCollection();
}
class A implements MyInterface {
List<String> collection;
A(){
collection = new ArrayList<>();
}
public ArrayList<> getCollection(){
return collection;
}
}
class B implements MyInterface{
List<String> collection;
B(){
collection = new ArrayList<>();
}
public ArrayList<> getCollection(){
return collection;
}
}
void methodTest(MyInterface genericObj)
{
genericObj.getCollection().add("1");
}

Refactoring a rigid code to eliminate if-else statement of checking instanceOf

Good day everyone,
I have a question regarding to refactoring a piece of code. The classes are structured as:
abstract class A
class A1 extends class A
class A2 extends class A
class A3 extends class A
abstract class AdditionalStuff {
abstract void function();
}
class AdditionalStuffForA1 extends AdditionalStuff
class AdditionalStuffForA2 extends AdditionalStuff
class AdditionalStuffForA3 extends AdditionalStuff
class Implementation {
List<A> aList;
.... //add A1, A2, A3 to aList
AdditionalStuff aS;
for (A instance: aList) {
if(instance instanceOf A1)
aS = new AdditionalStuffForA1();
else if(instance instanceOf A2)
aS = new AdditionalStuffForA2();
else
aS = new AdditionalStuffForA3();
aS.function()
}
}
The code above is rigid I think, because everytime when a new class An (for example A4 and AdditionalStuffForA4) is added, It's a must to modify the if else statements too.
I thought about using Decorator Pattern, but now I think Decorator Pattern cannot solve my problem. I would like to ask, could you please suggest me a way to refactoring the code above to eliminate the use of if-else statement? (Note that, I cannot add functions of AdditionalStuff to be inside A because they are used differently)
There are multiple approaches to this. But the simplest answer to extend your existing implementation would look something like this
abstract class A {
public abstract AdditionalStuff getAdditionalStuff();
}
class A1 extends class A {
#Override
public AdditionalStuff getAdditionalStuff() {
return new AdditionalStuffA1();
}
}
class A2 extends class A {
#Override
public AdditionalStuff getAdditionalStuff() {
return new AdditionalStuffA2();
}
}
class A3 extends class A {
#Override
public AdditionalStuff getAdditionalStuff() {
return new AdditionalStuffA3();
}
}
abstract class AdditionalStuff {
abstract void function();
}
class AdditionalStuffForA1 extends AdditionalStuff
class AdditionalStuffForA2 extends AdditionalStuff
class AdditionalStuffForA3 extends AdditionalStuff
class Implementation {
List<A> aList;
.... //add A1, A2, A3 to aList
AdditionalStuff aS;
for (A instance: aList) {
aS = instance.getAdditionalStuff();
aS.function()
}
}
The classic "Text book method" would be the Visitor Pattern.
First, you need to define a visitor interface:
interface AVisitor<T> {
T visitA1(A1 a1);
T visitA2(A2 a2);
T visitA3(A3 a3);
}
Then you need to extend your A class by an abstract method to recieve visitors:
abstract class A {
...
public <T> abstract T recieve(AVisitor<T> visitor);
}
And your classes A1, A2, and A3 need the implementation for the recieve methods:
class A1 extends A {
...
public <T> T recieve(AVisitor<T> visitor) {
return visitor.visitA1(this);
}
}
class A2 extends A {
...
public <T> T recieve(AVisitor<T> visitor) {
return vistor.visitA2(this);
}
}
class A3 extends A {
...
public <T> T recieve(AVisitor<T> visitor) {
return visitor.visitA3(this);
}
}
And finally you must define the different visit Methods in your implementation class:
class Implementation implements AVisitor<AdditionalStuff> {
void ... () {
List<A> aList;
....
for (A instance : aList) {
AdditionalStuff aS = instance.recieve(this);
aS.function();
}
}
public AdditionalStuff visitA1(A1 a1) {
return new AdditionalStuffForA1();
}
public AdditionalStuff visitA2(A2 a2) {
return new AdditionalStuffForA2();
}
public AdditionalStuff visitA3(A3 a3) {
return new AdditionalStuffForA3();
}
}
This method has the advantage that your A, A1, A2 and A3 classes don't need any knowledge about these AdditionalStuff-classes. The disadvantage is when you need a fourth class A4, you have to add a visitA4 method to the interface ... and in every single class which implements this AVisitor interface. (EDIT: But in difference to your if (... instanceof ...) else if (... instanceof ...) methods: The visitor approach would guarantee that you do not miss a special instance check. If you forget to add an implementation for handling your A4 classes, the compiler will tell it to you.
Edit: Fix code of Implementation class
It's a little hard to make sensible suggestions without understand what your code is actually meant to do but I'd look into the factory pattern, i.e. provide a factory for each AdditionalStuff subclass, register it in some map and look it up via instance's class:
interface AdditionalStuffFactory {
AdditionalStuff create();
}
class AdditionalStuffA1Factory implements AdditionalStuffFactory {
public AdditionalStuff create() {
return new AdditionalStuffForA1();
}
}
Then you have a Map<Class<? extends A>, AdditionalStuffFactory> somewhere, which would get filled with factory instances, e.g. registry.put(A1.class, new AdditionalStuffA1Factory() );
Your loop would then look like this:
for (A instance: aList) {
AdditionalStuff aS = registry.get(instance.getClass()).create();
aS.function();
}
Of course there are further optimizations, e.g. having "registry" delegate the calls thus getting something like registry.createFor(instance) but you should get the point.
Addition another AdditionalStuff would then require the following:
creating the additional class (you always do that)
creating a factory for that class (unless you can provide for some generic factory)
register the new factory in your registry (that could be done via some lookup mechanism, e.g. via CDI, but I'll not get deeper into this here)
You can try the following.
First of all avoid using inheritance if you don't have to. For example your AdditionalStuff only defines a contract the method function which needs to implemented by the various classes you have. This can altered to be an interface instead of an abstract class.
With this in hand just change the list to hold the various interface implementations e.g:
List<SomeInterface> list = new ArrayList<>;
Collections.addAll(list, new ClassA(), new ClassB());
then just iterate through all of them in a single line and do:
list.forEach(SomeInterface::function);
This way you'll avoid the intricate inheritance (which is uneeded here), as well as the introspection and everything else.
Use interfaces!
In Java 8 or higher, interfaces can have default method implementation.
You can define:
public interface AdditionalStuff {
void function(Object... params);
}
public interface AdditionalStuffForA1 extends AdditionalStuff {
default void function(Object... params) {
//do something with params here
System.out.println("implementation for A1");
}
}
public interface AdditionalStuffForA2 extends AdditionalStuff {
default void function(Object... params) {
//do something with params here
System.out.println("implementation for A2");
}
}
And create your classes with the proper interface:
public abstract class A implements AdditionalStuff {
}
public class A1 extends A implements AdditionalStuffForA1 {
}
public class A2 extends A implements AdditionalStuffForA2 {
}
With this execution:
List<A> aList = new ArrayList<>();
aList.add(new A1());
aList.add(new A2());
aList.add(new A2());
for (A a : aList) {
a.function(23, 45, "string...");
}
Will print:
implementation for A1
implementation for A2
implementation for A2
The additional behavior can be controlled with the parameter (Object ... params)
I can think of two good approaches. Both are variations on the "factory" design pattern.
Approach 1 is to make the A classes responsible for creating instances of AdditionalStuff subtypes.
abstract class A {
abstract AdditionalStuff makeAdditionalStuff();
...
}
class A1 extends class A {
AdditionalStuff makeAdditionalStuff() {
return new AdditionalStuffForA1();
...
}
class Implementation {
List<A> aList;
.... //add A1, A2, A3 to aList
for (A instance: aList) {
instance.getAdditionalStuff().function()
}
}
Approach 2 is to abstract out the instanceOf tests into a factory method:
AdditionalStuff getAdditionalStuff(A instance) {
if (instance instanceOf A1) {
return new AdditionalStuffForA1();
} else if(instance instanceOf A2) {
return new AdditionalStuffForA2();
} else {
return new AdditionalStuffForA3();
}
}
or better:
AdditionalStuff getAdditionalStuff(A instance) {
if (instance instanceOf A1) {
return new AdditionalStuffForA1();
} else if (instance instanceOf A2) {
return new AdditionalStuffForA2();
} else if (instance instanceOf A3) {
return new AdditionalStuffForA3();
} else {
throw new RuntimeException("not implemented");
}
}
You can replace the if instanceof tests with a switch, and switch on the class name for instance. But for a small number of subclasses, there is little to be gained by doing that. (IMO)
the own method on the abstract or interface implementation, can validate it self, preventing many if, using just one if inside every one of this implementations. adding this on architecture from #Lup.

Return data type the same as class name via superclass?

I have an abstract class which has one abstract method. I want this method to return the same data type as the class which is overriding the method without having to cast the result of create or having to make a new method declaration on each subclass. I want it to all be declared seemlessly from the parent class.
I want the method to return a object whose data type is the same as the class it was called on.
EDIT: I removed print as people are getting confused with what I am asking
abstract class A
{
public abstract ... create();
}
class B extends A
{
#override
public ... create()
{
return new B...;
}
}
class C extends A
{
#override
public ... create()
{
return new C...;
}
}
Such that
B x1 = new B();
B x2 = x1.create();
// Since create was called on a B object
// a B object is returned, NOT AN "A" object
C y1 = new C();
C y2 = y1.create();
// create makes a C object this time,
// because it's called on a C object
// Problem: create() returns A object, even when
// called from class B or C.
// I want create() to return a B object if called from a B object.
What would be a good way of going about this? Thanks.
I no longer think this is the right answer. It's an answer, but is over-complicated. See my other answer.
There is no notion of a "self" type in Java's generics. The best you can do is to use self-bounded generics:
abstract class A<T extends A<T>>
{
public abstract T create();
}
Then, in your subclasses:
class B extends A<B>
{
#override
public B create()
{
return new B...;
}
}
Actually, there is an easier way to do it than with my other answer: just use a covariant return type in the subclass:
abstract class A {
public abstract A create();
}
class B extends A {
#Override public B create() {
return new B...
}
}
This is more pleasant if you are dealing with instances of A, since you don't have to make it generic (or, shudder, raw).
It also gives just as much of a guarantee that it returns a "self" type, i.e. no guarantee at all.
this.getClass() to get the class object, or, this.getClass().getSimpleName() to get a string of class name.
I have to question the design approach.
I'd be going for
abstract class A {
abstract Supplier<? extends A> create();
}
with
class B extends A {
public Supplier<B> create() {
return B::new;
}
}
(and C accordingly).
Then, there is
A b = new B();
A anotherB = b.create().get(); // will create a B
A c = new C();
A anotherC = c.create().get(); // will create a C
You don't need to make your create method abstract. If all the subclasses have a no-argument constructor, then you can just write this (in class A)
public A create() {
try {
return getClass().newInstance();
} catch (InstantiationException | IllegalAccessException e) {
return null;
}
}
This checks the class of the object that you called the method on; and creates a new object of the same class, using its no-argument constructor.
Update
OP's comment suggests that they don't want to have to cast the returned value. If this is a requirement, then the casting can be avoided by changing the method signature as follows.
public <T extends A> T create() {
try {
return getClass().newInstance();
} catch (InstantiationException | IllegalAccessException e) {
return null;
}
}

Java generics return holder object from a generic method

In the following:
public interface SomeInteface<A, B> {
public B doSomething(A a);
}
I want to implement a version where the method doSomething returns the parameter a back.
I tried a Holder class;
class Holder<A> {
public A value;
public(A a){this.value = a;}
}
and return Holder. However, I am not sure how to define an implementation class of SomeInterface so that I am able to do this.
The following does not even compile:
public class SomeImplementation<X> implements SomeInterface<T> {
private class Holder<A> {
public A value;
public class Holder<A>{
public A value;
public(A a){this.value = a;}
}
}
class Implementation<A, Holder<A>> implements SomeInterface<A, Holder<A>>{
public Holder<A> doSomething(A a){
//do stuff
return new Holder(a);
}
}
}
What am I messing up here?
It needs to be
class Implementation<A> implements SomeInteface<A, Holder<A>>{
public Holder<A> doSomething(A a){
//do stuff
return new Holder<A>(a);
}
}
In the classname you define the generic variables and their constraints. You don't need a Holder variable.
I don't understand why you make it so difficult. You say
I want to implement a version where the method doSomething returns the
parameter a back.
Well, you can do just that:
public class SomeImplementation<A> implements SomeInterface<A, A> {
public A doSomething(A a) {
// do stuff
return a;
}
}
No need for a Holder class.
The interface SomeInterface does not put any constraints on the type parameters, so there's no reason why they can't be the same.
Alternatively, you can allow your implementation to be parameterized with two different types A and B where A extends B (could be useful in some cases):
public class SomeImplementation<A extends B, B> implements SomeInterface<A, B> {
public B doSomething(A a) {
// do stuff
return a;
}
}

Passing Derived Class to a method which needs to override expecting a base class

I have a class A, with an abstract method doAction(BaseClass obj) expecting a param of type BaseClass
public class A {
//....
abstract void doAction(BaseClass obj);
//....
}
Now, I have another class B which needs to extend A. However, B's doAction method needs to use an object DerivedClass which extends BaseClass.
public class B extends class A {
//..
void doAction(DerivedClass obj) {
obj.callMethodAvailableOnlyInDerivedClass();
}
}
How do I handle this situation where I need to pass param of type DerivedClass to the method to be overridden while it is expecting a BaseClass ?
Thanks!
You make the base class generic:
public class A<T extends BaseClass> {
//....
abstract void doAction(T obj);
//....
}
and the subclass parameterized with the derived class:
public class B extends A<DerivedClass> {
//..
void doAction(DerivedClass obj) {
obj.callMethodAvailableOnlyInDerivedClass();
}
}
Without generics, it's not possible because B would break the contract of A: A accepts any kind of BaseClass, but you retrict B to only accept a specific subclass. This does not respect the Liskov principle.
You can use:
public abstract class A<T extends BaseClass> {
//....
abstract void doAction(T obj);
//....
}
public class B extends class A<DerivedClass> {
//..
void doAction(DerivedClass obj) {
obj.callMethodAvailableOnlyInDerivedClass();
}
}
There is no Contra-Variance of parameters in java, since it is not safe.
Assume you have A a = new B();
And then you invoke a.doAction(new BaseClass()) What will happen?
It will cause a run time error, since B does not know "what to" with a BaseClass. java wants to avoid it - so there is no covariance of parameters.

Categories