I want to generalize a repetitive piece of Java code for a lot of (~40-50) similar entities (in my case, this piece is indexing of files with these entities).
I tried to refactor it with generic method, but, as a result, I get a constructor of generic class that is apparently prohibited in Java. To avoid this, I implemented abstract factory pattern and here's what I've get.
public <E extends CMObject, F extends IndexedFile<E>> F indexFile(CMFactory<E, F> factory) {
F items;
ByteBuffer[] buffs;
// ...filling buffers...
items = factory.makeFile(buffs); // as I cannot do items = new F(buffs)
return items;
}
public CityFile getCities() {
return indexFile(new CityFactory());
}
public ContinentFile getContinents() {
return indexFile(new ContinentFactory());
}
// a lot of more
This solves an issue of creating an instance of generic class. However, I now face a task of creating a concrete factory for each single entity that seems to be a lot of monotonous work as they all look like each other.
public abstract class CMFactory<E extends CMObject, F extends IndexedFile<E>> {
public abstract F makeFile(ByteBuffer[] buff);
}
public class CityFactory extends CMFactory<City, CityFile> {
#Override
public CityFile makeFile(ByteBuffer[] buff) {
return new CityFile(buff);
}
}
public class ContinentFactory extends CMFactory<Continent, ContinentFile> {
#Override
public ContinentFile makeFile(ByteBuffer[] buffs) {
return new ContinentFile(buffs);
}
}
The question is: is there any way to automatize creation of such factories? Or maybe is there another pattern that can at least make such creation less painful?
I tried to use IntelliJ IDEA's Replace Constructor with Factory Method refactor, but it didn't help me.
Since your CMFactory is almost a functional interface you can use constructor handles instead of implementing CMFactory for each concrete class:
Make CMFactory an interface:
public interface CMFactory<E extends CMObject, F extends IndexedFile<E>> {
public abstract F makeFile(ByteBuffer[] buff);
}
and then write
public CityFile getCities() {
return indexFile(CityFile::new);
}
You can even discard CMFactory and use java.util.Function:
public <E extends CMObject, F extends IndexedFile<E>> F indexFile(Function<ByteBuffer[],F> factory) {
ByteBuffer[] buffs;
// ...filling buffers...
return factory.apply(buffs);
}
Related
I have a class that represents a vendor service and all their services have an authentication and an execute method.
I started thiking of an abstract class that represents this as below.
The thing is each of their services require a different request object, so I thought of using generics.
The problem is that if use it, I can't handle the specifics of each request object. Each children must use some methods from the type.
1) Should I try to make this way I'm trying, or remove this executeRequest method from the abstract class and each subclass implement it with the correct type?
2) I always hear "prefer composition over inheritance". Should I move the executeRequest to an interface?
Thanks in advance!
public abstract class VendorService {
private final VendorInitialization VendorInitialization;
//a bean with some auth params
public VendorService(VendorInitialization VendorInitialization) {
this.VendorInitialization = VendorInitialization;
}
protected abstract <T> boolean validateRequest(T requestObject) throws VendorServiceBadRequest;
protected abstract <T, P> P executeRequest(T requestObject);
}
public class VendorServiceAllocation extends VendorService {
public VendorServiceAllocation(VendorInitialization VendorInitialization) {
super(VendorInitialization);
}
#Override
protected <T> boolean validateRequest(T requestObject) throws VendorServiceBadRequest {
//List<BeanAllocation> requestObject = new Arraylist<>(); //I was using like this before
//TODO: how to handle it as list of on this specific case?
if (requestObject == null || requestObject.size() == 0) {
throw new VendorServiceBadRequest(String.format("The list must have at least one element"));
}
//TODO: requestObject.get(0).getMySpecificFieldFromBeanAllocation will not work
//some checks
return true;
}
#Override
protected <T, P> P executeRequest(T requestObject) {
//executes and return a list of objects specific to this class
return new List<BeanAllocationResponse>();
}
}
Edit, for clarification:
In the child class VendorServiceAllocation, I need to use some methods that are specific of that type.
E.g.: Inside executeRequest, I need to call requestObject.customFunctionFromChild()
I think niceman hit the nail on the head, though I am not quite sure what you are asking. eg.
abstract class Service<T,P>{
abstract public P processRequest(T t);
}
Then you can implement it in one of two ways.
class StringService extends Service<String, String>{
public String processRequest(String t){
return t;
}
}
Or you could leave it to still be Generic and the actual instances would have the different types.
class OtherService<T> extends Service<T, String>{
public String processRequest(T t){
return t.toString();
}
}
Where you could use it as,
OtherService<Integer> is = new OtherService<>();
Forgive me if there are syntax problems. The goal of this is not to get the code perfect but to get the design.
I have an interface ITable<T>
public interface ITable<T> {
public Collection<T> getEntries();
public void add(CustomObj value);
public Collection<CustomObj> getCustomObjects();
}
that is used by two classes:
TableOne<CustomObj> and TableTwo<Pair<CustomObj, CustomObj>>
Then I have an interface that applies these tables using a function
public interface ITableFunction<T> {
public abstract Collection<ITable<?>> execute(Collection<ITable<T>> tables);
}
My dilemma occurs when I try to create a generic Abstract class
public abstract class AbstractTableFunctionCombined<T> implements ITableFunction<T>{
private boolean someBool;
public AbstractTableFunctionCombined(boolean someBool){
this.someBool = someBool;
}
#Override
public Collection<ITable<?>> execute(Collection<ITable<T>> tables){
// What i would like to do, but can't right now:
ITable<T> combinedTable;
if (someBool){
combinedTable = new TableOne();
} else {
combinedTable = new TableTwo();
}
for(ITable<T> table : tables){
combinedTable.addAll(table.getCustomObjects());
}
for(T entry : table.getEntries()){
execute(entry);
}
}
public abstract void execute(T entry);
}
The issue is that I can't guarantee that the type T is the same as the table that I'm trying to instantiate. I thought I had to create some kind of relationship from the Pair<CustomObj, CustomObj> and the regular CustomObj. I tried creating a Entry interface that these both would use, and having ITable<T> be ITable<T extends Entry> but again this runs into the same problem.
I also thought that maybe I can make the TableOne and TableTwo classes use the same Generic i.e. TableTwo<T> implements ITable<T>, but TableTwo has a hard restriction of using Pair<CustomObj, CustomObj>.
Would I have to create two separate classes: AbstractTableFunctionOne<CustomObj> and AbstractTableFunctionTwo<Pair<CustomObj, CustomObj>> ? I would like to avoid this as it would be a lot of duplicated code.
Or am I over forcing this Object oriented design? Should TableOne and TableTwo not even implement the same interface?
This Interface has some issus:
public interface ITableFunction {
public abstract execute(Collection<ITable<T>> tables);
}
You need a return type and a Generic:
public interface ITableFunction<T> {
public abstract void execute(Collection<ITable<T>> tables);
}
and return type of Method
public Collection<ITable<T>> execute(Collection<ITable<T>> tables){
..
should be Collection OR void in declaration AND implementation.
I have an abstract class (Candy) with a generic collection (Flavors). Candy has a factory method to produce concrete instances of itself. It also has methods to get an instance of the generic flavor appropriate to the concrete candy and to add the flavor to its collection.
I know the getter is working, because if I cast the flavor from the CandyStore, the methods unique to the concrete flavor work fine. But the very last line, the addFlavor(flavor), errs (Eclipse) on me. The error is: "The method addFlavor(capture#5-of ? extends IFlavor) in the type ICandy is not applicable for the arguments (IFlavor)." Can anyone explain what is going on?
Interface:
public interface ICandy <Flavor extends IFlavor> {
public Flavor getFlavorForCandy();
public void addFlavor(Flavor flavor);
}
Abstract Class:
public abstract class AbstractCandy<Flavor extends IFlavor> implements ICandy<Flavor> {
public static ICandy<? extends IFlavor> buildCandy(String flavor){
if(flavor.equals("Jolly Rancher")
return new JolRanchCandy();
}
public Flavor getFlavorForCandy() {
return (Flavor) new CandyFlavor();
}
public void addFlavor(Flavor flavor) {
... //implemented
}
}
Concrete Class:
public class JolRanchCandy extends AbstractCandy<JolRanchFlavor> {
... //implemented
}
Used By:
public class CandyStore {
private ICandy<? extends IFlavor> candy;
private IFlavor flavor;
public void createCandy() {
candy = AbstractCandy.buildCandy("Jolly Rancher");
flavor = candy.getFlavorForCandy(); //returns a JolRanchFlavor
flavor.setName("Apple"); //etc for creating flavor
candy.addFlavor(flavor); //no luck
}
}
Edit: For clarity, JolRanchFlavor extends CandyFlavor implements IJolRanchFlavor and CandyFlavor implements IFlavor.
Try this...
public <T extends IFlavor> void createCandy() {
ICandy<T> candy= (ICandy<T>) AbstractCandy.buildCandy("Jolly Rancher");
T flavor= candy.getFlavorForCandy();
flavor.setName("Apple");
candy.addFlavor(flavor);
}
The problem is the declaration of private ICandy<? extends IFlavor> candy. Since the type of the candy is unknown and therefore ? the compiler doesn't know exactly what kind of IFlavor addFlavor should take. You just need to define a generic holder for the IFlavor type so that it is preserved.
First off, I want to say there is no use case for this. The only thing I am trying to do is explore if this is possible.
What I am trying to do is "rebrand" the return signature of a method in the base interface to that of a child interface.
The goal: declare and implement a method once, but vary the return type to match subinterfaces. I have figured out how to achieve this in some cases, but it breaks down in certain situations.
Imagine if I have base interface B and it has a method B doWork(). Also, there is an implementation of B that implements doWork(). Due to the nature of doWork(), this implementation should be the only one that exists.
Now, this is pretty easy to do with Generics. For the above example:
interface B<T extends B> {
T doWork();
}
class BImpl<T extends B> implements B<T> {
#Override
public T doWork() { return something; }
}
And the child interface/impl would look like this maybe:
interface C extends B<C> {
void somethingCSpecific();
}
class CImpl extends BImpl<C> implements C {
#Override
public void somethingCSpecific() { }
}
Anyone constructing CImpl would see that doWork() returns a C.
C obj = new CImpl().doWork() // The money shot. No casting needed.
And here is where it breaks down... Imagine B now looks like this:
public interface B<T extends B> {
T thisOrThat(T that);
boolean something();
}
And I want to do this in BImpl:
class BImpl<T extends B> implements B<T> {
#Override
public T thisOrThat(T that) {
if (that.something())
return that;
return this; // Error!! _this_ might be a different T than _that_.
}
#Override
public boolean something() { return whatever; }
}
Note where the error happens.
Obviously, this can't work without an unsafe and dubious cast. But if I knew that the implementation of this in the above thisOrThat method was the same as the implementation of that, everything would be ok.
So, to my question. Is there a way to restrict this and that to the same type, without knowing that type a priori?
Or maybe is there a different way to go about doing this, but having the same result? Namely only having to declare AND implement thisOrThat() just once, yet have the return type adapt to the subinterface?
Thanks.
Make your class BImpl abstract and add a view method to it which is implemented by the specific classes extending your abstract base class:
public abstract class BImpl<T extends B<T>> implements B<T> {
#Override
public T thisOrThat(T that) {
if (that.something())
return that;
return this.asT();
}
#Override
public boolean something() {
// TODO Auto-generated method stub
return false;
}
protected abstract T asT();
}
Every of your classes still needs to implement T asT() then, but this is simple and compiles without warning:
public class C extends BImpl<C> implements B<C> {
#Override
protected C asT() {
return this;
}
}
If I understand your problem correctly, then the way to solve it is with a sort of self-referential generic: B<T extends B<T>>.
I think what you want is class BImpl implements B<BImpl>, in which case everything type checks normally.
I have the concept of NodeTypes and Nodes. A NodeType is a bunch of meta-data which you can create Node instances from (a lot like the whole Class / Object relationship).
I have various NodeType implementations and various Node implementations.
In my AbstractNodeType (top level for NodeTypes) I have ab abstract createInstance() method that will, once implemented by the subclass, creates the correct Node instance:
public abstract class AbstractNodeType {
// ..
public abstract <T extends AbstractNode> T createInstance();
}
In my NodeType implementations I implement the method like this:
public class ThingType {
// ..
public Thing createInstance() {
return new Thing(/* .. */);
}
}
// FYI
public class Thing extends AbstractNode { /* .. */ }
This is all well and good, but public Thing createInstance() creates a warning about type safety. Specifically:
Type safety: The return type Thing for
createInstance() from the type
ThingType needs unchecked conversion
to conform to T from the type
AbstractNodeType
What am I doing wrong to cause such a warning?
How can I re-factor my code to fix this?
#SuppressWarnings("unchecked") is not good, I wish to fix this by coding it correctly, not ignoring the problem!
You can just replace <T extends AbstractNode> T with AbstractNode thanks to the magic of covariant returns. Java 5 added support, but it didn't receive the pub it deserved.
Two ways:
(a) Don't use generics. It's probably not necessary in this case. (Although that depends on the code you havn't shown.)
(b) Generify AbstractNodeType as follows:
public abstract class AbstractNodeType<T extends AbstractNode> {
public abstract T createInstance();
}
public class ThingType<Thing> {
public Thing createInstance() {
return new Thing(...);
}
}
Something like that should work:
interface Node{
}
interface NodeType<T extends Node>{
T createInstance();
}
class Thing implements Node{}
class ThingType implements NodeType<Thing>{
public Thing createInstance() {
return new Thing();
}
}
class UberThing extends Thing{}
class UberThingType extends ThingType{
#Override
public UberThing createInstance() {
return new UberThing();
}
}