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.
Related
I'm pretty new to java and not particularly sure how to initialize a generic type / child class from the 'base' class.
Essentially I have a bunch of classes that extend the abstract class BaseClass that need to be initialized and added to the instance Map if a key is not present.
The child class is re-used multiple times but is dynamically created based on the key parameter.
I would like to avoid reflection and don't mind changing the template if it's not 'the Java way'.
What I currently have:
public abstract class BaseClass<T> {
protected Map<String, T> instance = new HashMap<String, T>();
public T Get(String key) {
if (this.instance.containsKey(key)) {
return this.instance.get(key);
}
T item = new T(key); // Obviously this line errors but you get the idea
instance.put(key, item);
return item;
}
}
// Example top class which extends my base class
public class TopClass extends BaseClass<TopClass> {
public TopClass(String key) {
// Do unique initialization stuff
}
}
Since generic types are erased at runtime, you cannot do this. You can instead use a Class variable as follows:
public T Get(Class<T> clazz, String key) throws Exception {
if (this.instance.containsKey(key)) {
return this.instance.get(key);
}
T item = clazz.getDeclaredConstructor(String.class).newInstance(key);
instance.put(key, item);
return item;
}
I have another approach to this.
Have an interface MyInterface.
public interface MyIinterface{
public void doSomething();
}
Create an many implementations of this interface.
#Component
public class MyImplementation1 implements MyInterface{
#Override
public void doSomething(){
}
}
Use spring core jars in the dependency.
Annotate all the implementations with #Component.
#Component
public class MyImplementation1 implements MyInterface{
.
.
Have a method in some Util class that will get you the implementation based on a string key.
public static MyInterface getImplementation(String name){
ApplicationContext context;
return context.getBeanByName(name);
}
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);
}
I have some base class that implements iterable
public class EntityCollection implements Iterable<Entity> {
protected List<Entity> entities;
public EntityCollection() {
entities = new ArrayList<Entity>();
}
public Iterator<Entity> iterator() {
return entities.iterator();
}
... etc
This is subclassed.
public class HeroCollection extends EntityCollection {
public void doSomeThing() { ... }
I would like to do the following:
HeroCollection theParty = new HeroCollection();
theParty.add(heroA);
theParty.add(heroB);
for (Hero hero : theParty){
hero.heroSpecificMethod();
}
But this fails at compile time, because the iterator is returning entities, not heroes. I am looking for some way to restrict the list such that it can contain only the types of the subclass, so that I can call methods which are specific to the subclass on the result of the iterator. I know it must use generics somehow but I can't seem to figure out how exactly to structure it.
I would suggest making EntityCollection generic.
public class EntityCollection<T extends Entity> implements Iterable<T> {
protected List<T> entities;
public EntityCollection() {
entities = new ArrayList<T>();
}
public Iterator<T> iterator() {
return entities.iterator();
}
... etc
public class HeroCollection extends EntityCollection<Hero> {
...
}
Then, HeroCollection's iterator method will return an Iterator<Hero>
(Also note: the way you're designing your collections (with separate methods for specific types of collections) suggests that your code may be poorly designed. However, if so, that's a separate problem.)
Is there a better "workaround" than this? I want to avoid the use of a PREFIX (local var) when accessing the methods on TableMap.
public class TableMap extends TreeMap<String, String> {
public String field1, field2, field3;
public TableMap(Tables table){}
public void method(){}
public void method2(){}
public void method3(){}
...
}
workaround!
public enum Tables {
table1, table2, table3;
public final TableMap MAP=new TableMap(this);
private Tables(){}
}
needed!
public enum Tables extends TableMap {
table1, table2, table3;
public Tables(){
super(table);
}
}
Example throughout the code:
// workaround!
Tables.table1.MAP.method();
Tables.table2.MAP.method();
Tables.table3.MAP.method();
...
// needed!
Tables.table1.method();
Tables.table2.method();
Tables.table3.method();
...
In Java, enum types must extend java.lang.Enum. Since Java types can every only extend a single type, you might think that public class TableMap extends Enum might work, but no, the compiler won't allow this.
In my own code, I use enums often as mere keys because they are so hostile. I have them implement a common interface and then use a factory to look up specific implementations of "worker" instances that I can then use.
One way to get closer to the syntax that you want is to use the delegate pattern:
public enum Tables {
...
public void method() {
MAP.method();
}
}
I think you may be trying to put too much intelligence into the enum.
I have found this approach very useful. It avoids many of the issues arising from the fact that you cannot extend enums (well actually you can but not in a very useful way).
Essentially, make the enum a sub-class and pass its characteristics up to your super class as an EnumSet. This way you still get all the benefits of enums including type safety.
public static class MappedEnum<E extends Enum<E>> extends TreeMap<String, String> {
public MappedEnum(EnumSet<E> e) {
// Whatever you like with the set.
}
public void method(E e) {
}
}
public static class Foo extends MappedEnum<Foo.Tables> {
public enum Tables {
table1, table2, table3;
}
public Foo() {
super(EnumSet.allOf(Tables.class));
}
#Override
public void method(Foo.Tables e) {
}
}
You could probably even use an EnumMap instead of your TreeMap for better efficiency.
It looks like this is impossible to do, but does anyone have a clever way around this problem?
public class SomeClassIterableWrapper<S, T extends SomeClass & S> implements Iterable<S>
Where S is supposed to be an interface of some unknown type and SomeClass is a 2D array with a row index, similar in functionality to a bidirectional JDBC resultset. Subclasses of SomeClass have custom getters and setters for each column. I want to be able to iterate through this structure like I would a List. I want to implement a common interface between my SomeClass and Bean to have access to the getters and setters. As such S needs to be that interface. However the declaration I provided does not work. Is there a way to work around this?
edit to show my desired implementation:
public class SomeClassIterableWrapper<S, T extends SomeClass & S> implements Iterable<S>{
T object;
public SomeClassWrapper(T object){
this.object = object;
}
#Override
public Iterator<S> iterator() {
object.setIndex(-1);
return new SomeClassIterator<S>();
}
private class SomeClassIterator<S> implements Iterator<S> {
#Override
public boolean hasNext() {
return object.index() < object.rowSize() - 1;
}
#Override
public S next() {
object.next();
//safe because only interface methods allowed, can't further manipulate index
return object;
}
#Override
public void remove() {
object.deleteRow();
}
}
Can't you parameterize SomeClass with S? Then you could have
public class SomeClassIterableWrapper<S, T extends SomeClass<S>>
implements Iterable<S>{
I think the S in extends SomeClass & S
public class SomeClassIterableWrapper
has to be a definite class because in this context,
S has to be a class that is extending something.
Is there a way you can narrow down what the
potential classes that are used in place of S are?
You could use multiple ampersands if you have multiple
classes that T should extend
I confess that I don't fully comprehend the problem but this is what I suggest:
Create an interface of S. It contains one method ad it returns the S object.
public interface SWrapper<S> {
S getS();
}
Then create an implementation:
public class SImpl implements SWrapper<SImpl> {
#Override
public SImpl getS() {
return this;
}
}
You can now create:
public class SomeClass<T extends SomeClass & SWrapper<T>> {
private final T object;
public SomeClass(T object) {
this.object = object;
}
}
You will have to modify your usage a bit but perhaps it works.