I have a class A that works with List<String>. But nobody outside this class should need to know that it works with strings. However, I also want to supply the concrete implementation the class should use for it's List (via dependency injection).
A should look like this
public class A {
private ListFactory listFactory; //this gets injected from the outside
public A(ListFactory listFactory) {
this.listFactory = listFactory;
}
public void a() {
List<String> = listFactory.createList();
//...
}
}
And the caller class B something like this
public class B {
public void b() {
ListFactory factory = new ArrayListFactory(); //we want class A to use ArrayList
A a = new A(factory);
//...
}
}
ListFactory would be an interface which is implemented by ArrayListFactory to create ArrayLists.
Quintessence:
I don't want that B has to mention String somewhere. And I also don't want that A has to mention ArrayList somewhere.
Is this possible? And how would ListFactory and ArrayListFactory have to look?
This is simpler than you're making it, I think:
public interface Factory {
public <T> List<T> create();
}
public class FactoryImpl implements Factory {
public <T> ArrayList<T> create() {
return new ArrayList<T>();
}
}
...
Factory f = new FactoryImpl();
List<String> strings = f.create();
...
Seems you wrote all you need. Factories will look like:
interface ListFactory<K, T extends List<K>> {
T create();
}
class ArrayListFactoryImpl implements ListFactory<String, ArrayList<String>> {
public ArrayList<String> create() {
return new ArrayList<String>();
}
}
class Sample {
public static void main(String[] args) {
ListFactory<String, ArrayList<String>> factory = new ArrayListFactoryImpl();
factory.create().add("string");
}
}
Another attempt thanks to more clear understanding of the issue:
interface ListFactory<T extends List> {
T create();
}
class ArrayListFactoryImpl implements ListFactory<ArrayList> {
public ArrayList create() {
return new ArrayList();
}
}
class ListWrapper<T> implements List<T> {
private final List impl;
public ListWrapper(List impl) {
this.impl = impl;
}
public boolean add(T t) {
if (!String.class.isAssignableFrom(t.getClass()))
throw new RuntimeException("Aaaaa");
return impl.add(t);
}
// so on...
}
class A {
A(ListFactory factory) {
List<String> stringsOnly = new ListWrapper<String>(factory.create());
}
}
class Sample {
public static void main(String[] args) {
ListFactory<ArrayList> factory = new ArrayListFactoryImpl();
new A(factory);
}
}
Related
Is there any way by which I can cast a reference of type Object, assuming that the reference could point to any class I defined, to said defined class at runtime?
I've been trying to work it out and the code I came out with is:
public class SomeTestBench {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
myEntity a = new myEntity("Hello Code!");
Receptacle cage = new Receptacle();
cage.injectYourEntity(a);
((cage.itsClass) cage.theEntity).exertExistence();
}
}
That unfortunately does not work, as the class argument to that cast must be static.
Rest of the code:
public class myEntity extends Object{
String warcry;
myEntity(String warcry){
this.warcry = warcry;
}
public void exertExistence(){
System.out.println(this.warcry);
}
}
public class Receptacle {
Object theEntity;
Class itsClass;
public void injectYourEntity(Object it){
this.theEntity = it;
this.itsClass = it.getClass();
}
public void prodIt(){
System.out.println(theEntity.getClass());
}
}
Why don't you just do this using Generics.
public static void main(String[] args) {
myEntity a = new myEntity("Hello Code!");
Receptacle<myEntity> cage = new Receptacle<>();
cage.injectYourEntity(a);
cage.theEntity.exertExistence();
}
//
//That unfortunately does not work, as the class argument to that cast must be static.
//
//Rest of the code:
class myEntity {
String warcry;
myEntity(String warcry){
this.warcry = warcry;
}
public void exertExistence(){
System.out.println(this.warcry);
}
}
class Receptacle<T> {
T theEntity;
public void injectYourEntity(T it){
this.theEntity = it;
}
public void prodIt(){
System.out.println(theEntity.getClass());
}
}
To call a no-arg method named exertExistence() on an object of unknown type, you have three choices:
Use generics. See answer by WJS.
Use reflection:
Receptacle cage = new Receptacle();
cage.injectYourEntity(new myEntity("Hello Code!"));
Method method = cage.itsClass.getMethod("exertExistence", null);
method.invoke(cage.theEntity, null);
Use an interface (recommended):
Receptacle cage = new Receptacle();
cage.injectYourEntity(new myEntity("Hello Code!"));
cage.theEntity.exertExistence();
interface MyInterface {
void exertExistence();
}
class myEntity implements MyInterface {
String warcry;
myEntity(String warcry){
this.warcry = warcry;
}
#Override
public void exertExistence(){
System.out.println(this.warcry);
}
}
class Receptacle {
MyInterface theEntity;
public void injectYourEntity(MyInterface it){
this.theEntity = it;
}
}
I have few classes that implements some interface. Now I want to create new class, which can extend one of them, based on runtime calculation while using interfaces methods. Let's talk in code:
public interface Interface {
public void doSomething();
}
public class A implements Interface {
#Override
public void doSomething() {
System.out.println("hello");
}
}
public class B implements Interface {
#Override
public void doSomething() {
System.out.println("hi");
}
}
These are existing classes, so now I need to do something like this (which is not working of course):
public class C<T extends Interface> extends T {
public void doSomethingElse() {
this.doSomething();
}
public static void main(String[] args) {
C c;
if(isSomethingLoaded) {
c = new C<A>();
} else {
c = new C<B>();
}
c.doSomethingElse();
}
}
Is it possible somehow, except the way that I pass argument Interface other to C's constructor and store to class property..?
A class cannot extend from its type parameter.
Use composition instead of inheritance:
public class C<T extends Interface> {
private final T foo;
public C(T foo){
this.foo = foo;
}
public void doSomethingElse() {
foo.doSomething();
}
public static void main(String[] args) {
C<?> c;
if(isSomethingLoaded) {
c = new C<>(new A());
} else {
c = new C<>(new B());
}
c.doSomethingElse();
}
}
You might even not need the type parameter here, but just use the interface type as argument/ member type.
I think it's situations like this which show why we have the rule of favouring composition over inheritance. Consider this solution using composition:
public class Test {
public interface Interface {
void doSomething();
}
public static class A implements Interface {
#Override
public void doSomething() {
System.out.println("Doing A");
}
}
public static class B implements Interface {
#Override
public void doSomething() {
System.out.println("Doing B");
}
}
public static class C implements Interface {
private Interface composedWith;
public C(Interface i) {
this.composedWith = i;
}
#Override
public void doSomething() {
this.composedWith.doSomething();
}
}
public static void main(String[] args) {
C c;
if(isSomethingLoaded) {
c = new C(new A());
} else {
c = new C(new B());
}
c.doSomething();
}
}
Personally, I feel this is a clearer and move flexible way of achieving what you are trying to do.
I have generic class :
public class Test<T> {
private Test<? extends T> myInstance;
public Test<? extends T> getInstance () {
return myInstance;
}
public void setInstance (Test<? extends T> argType) {
this.myInstance = argType;
}
}
And I have two classes in my class hierarchy relations:
public abstract class Alphabet {
//code here
}
and
public class A extends Alphabet{
public A() {
super();
System.out.print("This is A call");
}
}
Finally I have a class where I want to store make generic class Test with particular type and set new Instance of Object -> A through setInstance() method:
public static void main(String[] args) {
List<Alphabet> list = new ArrayList<Alphabet>();
Test<Alphabet> tAlphabet = new Test<Alphabet>();
tAlphabet.setInstance(new A()); //Here is compilation ERROR
}
But I have got the compilation error in line tAlphabet.setInstance(new A());
What is the issue with my generic class?
Your instance is a Test object as it's currently written, and you are supplying it with an Alphabet object instead. You probably want your instance to be of type Alphabet:
public class Test<T> {
private T myInstance;
public T getInstance() {
return myInstance;
}
public void setInstance(T argType) {
myInstance = argType;
}
}
This way, your Test stores an Alphabet instead of another Test.
It seems you have made things more complicated than needed. You probably want this in your Test class instead of what you actually have:
private T myInstance;
public T getInstance () {
return myInstance;
}
public void setInstance (T argType) {
this.myInstance = argType;
}
With this arrangement you would be free to setInstance(new A()) on a Test<Alphabet> instance.
In libgdx you can create a pool easily by using the abstract class Pool.
Since it is an abstract class you need to override it's methods anonymously when constructing it like this:
public Pool<String> pool = new Pool<String>() {
#Override
protected String newObject() {
return new String();
}};
What I'm trying to do now is put a wildcard for the generic type T which extends a abstract BaseClass like this:
protected static Pool<? extends GameCommand> commandPool = new Pool<? extends GameCommand>() {
#Override
protected <T extends GameCommand> newObject() {
return new T();
}
};
But it won't work. How can I get it?
What kind of type will I have to insert when overriding newObject()?
EDIT:
Pool references it's abstract method like this:
abstract public class Pool<T> {
(...)
abstract protected T newObject ();
(...)
}
If you make a small change like making a factory method, it can be done fairly simply. As long as you can assure that all subclasses of GameCommand have a default constructor. (Although, you could get around that with Objenesis).
Just do the following:
public static <T extends GameCommand> Pool<T> createCommandPool(final Class<T> clazz) {
return new Pool<T>() {
#Override protected T newObject() {
try {
return clazz.newInstance();
} catch (Exception e) {
throw new RuntimeException(e); // cause there isn't really much else you can do.
}
}
};
}
public static void main(String[] args) {
Pool<? extends GameCommand> gcPool = createCommandPool(GameCommand.class);
// MyCommand extends GameCommand
Pool<? extends GameCommand> mcPool = createCommandPool(MyCommand.class);
}
I am doing some exercises from the book Thinking In Java. I have some problems with one exercise. It says:
A constructor is a kind of factory method. Modify RegisteredFactories.java so that instead of using an explicit factory, the class object is stored in the List, and newInstance( ) is used to create each object.
How can I achieve that? Below is code for factory interface and RegisteredFactories class. Thank you
package typeinfo.factory;
public interface Factory<T> { T create(); } ///:~
package cont;
import typeinfo.factory.*;
import java.util.*;
class Part {
public String toString() {
return getClass().getSimpleName();
}
static List<Factory<? extends Part>> partFactories =
new ArrayList<Factory<? extends Part>>();
static {
// Collections.addAll() gives an "unchecked generic
// array creation ... for varargs parameter" warning.
partFactories.add(new FuelFilter.Factory());
partFactories.add(new AirFilter.Factory());
partFactories.add(new CabinAirFilter.Factory());
partFactories.add(new OilFilter.Factory());
partFactories.add(new FanBelt.Factory());
partFactories.add(new PowerSteeringBelt.Factory());
partFactories.add(new GeneratorBelt.Factory());
}
private static Random rand = new Random(47);
public static Part createRandom() {
int n = rand.nextInt(partFactories.size());
return partFactories.get(n).create();
}
}
class Filter extends Part {}
class FuelFilter extends Filter {
// Create a Class Factory for each specific type:
public static class Factory
implements typeinfo.factory.Factory<FuelFilter> {
public FuelFilter create() { return new FuelFilter(); }
}
}
class AirFilter extends Filter {
public static class Factory
implements typeinfo.factory.Factory<AirFilter> {
public AirFilter create() { return new AirFilter(); }
}
}
class CabinAirFilter extends Filter {
public static class Factory
implements typeinfo.factory.Factory<CabinAirFilter> {
public CabinAirFilter create() {
return new CabinAirFilter();
}
}
}
class OilFilter extends Filter {
public static class Factory
implements typeinfo.factory.Factory<OilFilter> {
public OilFilter create() { return new OilFilter(); }
}
}
class Belt extends Part {}
class FanBelt extends Belt {
public static class Factory
implements typeinfo.factory.Factory<FanBelt> {
public FanBelt create() { return new FanBelt(); }
}
}
class GeneratorBelt extends Belt {
public static class Factory
implements typeinfo.factory.Factory<GeneratorBelt> {
public GeneratorBelt create() {
return new GeneratorBelt();
}
}
}
class PowerSteeringBelt extends Belt {
public static class Factory
implements typeinfo.factory.Factory<PowerSteeringBelt> {
public PowerSteeringBelt create() {
return new PowerSteeringBelt();
}
}
}
public class RegisteredFactories {
public static void main(String[] args) {
for(int i = 0; i < 10; i++)
System.out.println(Part.createRandom());
}
}
here:
import java.util.*;
class Part {
public String toString() {
return getClass().getSimpleName();
}
static List<Class> partFactories = new ArrayList<Class>();
static {
// Collections.addAll() gives an "unchecked generic
// array creation ... for varargs parameter" warning.
partFactories.add(FuelFilter.class);
partFactories.add(AirFilter.class);
partFactories.add(CabinAirFilter.class);
partFactories.add(OilFilter.class);
partFactories.add(FanBelt.class);
partFactories.add(PowerSteeringBelt.class);
partFactories.add(GeneratorBelt.class);
}
private static Random rand = new Random(47);
public static Part createRandom() throws Exception {
int n = rand.nextInt(partFactories.size());
return (Part)(partFactories.get(n).newInstance());
}
}
class Filter extends Part {}
class FuelFilter extends Filter {
}
class AirFilter extends Filter {
}
class CabinAirFilter extends Filter {
}
class OilFilter extends Filter {
}
class Belt extends Part {}
class FanBelt extends Belt {
}
class GeneratorBelt extends Belt {
}
class PowerSteeringBelt extends Belt {
}
public class aa{
public static void main(String[] args) {
for(int i = 0; i < 10; i++)
try {System.out.println(Part.createRandom()); }catch (Exception e) {}
}
}
static List<Factory<? extends Part>> partFactories
thats the list,
it contains several factories and is initiated in the static block.
this code randomly creates objects via their factories using createRandom method
the idea is that instead of creating an object by calling new, you create one using its factory
all factories here implement the interface Factory, which means they have a method called create() that returns a new instance of the desired class (the one the factory belongs to)