So what I want to do is inject the instance of A created in MyGame into PlayScreen. Here is my code so far:
class MyGame extends Game {
public A a;
public void create() {
a = new A();
Injector injector = Guice.createInjector(new GameModule(this));
setScreen(new PlayScreen());
}
}
public class GameModule extends AbstractModule {
MyGame game;
public GameModule(MyGame game){
this.game = game;
}
#Override protected void configure() {}
#Provides
#Singleton
A getA() {
return game.a;
}
}
public class PlayScreen extends Screen {
#Inject A a;
public void render() {
// Using a
}
}
But in the method render() from PlayScreen, batch comes out as null.
However, if in MyGame I use injector.getInstance(A.class) everything works, I do not get null.
What am I doing wrong?
I solved it. As chrylis said, I had to use constructor injection instead of field injection. Here is the new code:
class MyGame extends Game {
public A a;
public void create() {
a = new A();
Injector injector = Guice.createInjector(new GameModule(this));
setScreen(injector.getInstance(PlayScreen.class));
}
}
#Singleton
public class PlayScreen extends Screen {
A a;
#Inject
PlayScreen(A a) {
this.a = a;
}
public void render() {
// Using a
}
}
GameModule remained the same.
Related
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.
Suppose I have two real implementations A and B of some interface. And there is also a Delegate-implemenation of that interface that delegates to either A or B dependending on some logic.
I want to have the Delegate injected into my client class so I marked A and B as #Alternatives to make that unambiguous. However, now the injection into the Delegate does not work since A and B are alternatives.
Any suggestions on how to solve this?
import org.jglue.cdiunit.AdditionalClasses;
import org.jglue.cdiunit.CdiRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.enterprise.inject.Alternative;
import javax.inject.Inject;
#RunWith(CdiRunner.class)
#AdditionalClasses({ CdiTest.A.class, CdiTest.B.class, CdiTest.Delegate.class })
public class CdiTest {
public interface Service {
void run();
}
#Alternative
public static class A implements CdiTest.Service {
#Override
public void run() {
System.out.println("Hi from A");
}
}
#Alternative
public static class B implements CdiTest.Service {
#Override
public void run() {
System.out.println("Hi from B");
}
}
public static class Delegate implements CdiTest.Service {
int counter = 0;
#Inject A a;
#Inject B b;
#Override
public void run() {
System.out.println("Hi from Delegate");
if ((counter++) % 2 == 0) a.run();
else b.run();
}
}
#Inject
private Service service;
#Test
public void test() {
service.run();
}
}
I think tha you need qualifiers instead of alternatives.
Have you tried using two qualifiers ServiceA and ServiceB? You could inject in the delegate both implementations and in real test the delegate.
EDIT
I don't think you should replace the delegate with a producer (from your example I understood that the delegate has some functional role in your application and is not only a
test/production switch).
I think that you could create another class with a producer method like this:
public class ServiceProducer {
private static final String SERVICE_A = "service-a";
private static final String SERVICE_B = "service-a";
private static final String SERVICE_DELEGATE = "service-delegate";
#Produces
#Chosen
public CdiTest.Service getService(#SystemProperty("service.choose.key") String chosenKey,
#ServiceA Instance<Service> a,
#ServiceB Instance<Service> b,
#ServiceDelegate Instance<Service> delegate) {
switch(chosenKey) {
case SERVICE_A:
return a.get();
case SERVICE_B:
return b.get();
case SERVICE_DELEGATE:
return delegate.get();
default:
throw new IllegalStateException("No Service implementation for type " + chosenKey);
}
}
}
The #SystemProperty is a useful solution to inject system properties found at http://juraj.blahunka.eu/2014/05/17/inject-jboss-system-properties/
So you example code could be changed in:
public class CdiTest {
public interface Service {
void run();
}
#ServiceA
public static class A implements CdiTest.Service {
#Override
public void run() {
System.out.println("Hi from A");
}
}
#ServiceB
public static class B implements CdiTest.Service {
#Override
public void run() {
System.out.println("Hi from B");
}
}
#ServiceDelegate
public static class Delegate implements CdiTest.Service {
int counter = 0;
#Inject #ServiceA Service a;
#Inject #ServiceB Service b;
#Override
public void run() {
System.out.println("Hi from Delegate");
if ((counter++) % 2 == 0) a.run();
else b.run();
}
}
#Inject
#Chosen
private Service service;
#Test
public void test() {
service.run();
}
}
This way you inject implementations A and B inside the delegate (without using the producer) and the produced one in your test class (choosing the correct implementation with a system property named "service.choose.key").
Suppose I have defined a class with interface like this:
public class myClass {
public void test() {
//here I want to trigger `onStartListener`
}
interface OnStartListener {
public void onStart();
}
}
and class B I have defined like this:
public class ClassB implements myClass.OnStartListener {
public void ClassB() {
myClass test1 = new myClass();
myClass.test();
}
#Override
public void onStart() {
System.out.println("start triggered");
}
}
How can I trigger OnStartListener from test method of myClass so ClassB can handle it?
Yes, you need to subscribe your listener and call the method in the class A:
public class ClassB implements myClass.OnStartListener {
public void ClassB() {
myClass test1 = new myClass(this);
//test1.setListener(this);
myClass.test();
}
#Override
public void onStart() {
System.out.println("start triggered");
}
}
and
public class myClass {
OnStartListener myListener;
public myClass(OnStartListener myListener) {
this.myListener = myListener;
}
public void test() {
//here I want to trigger `onStartListener`
myListener.onStart();
}
interface OnStartListener {
public void onStart();
}
}
Have a look at how frameworks like swing handle listeners. Basically you need to "register" the listener instance (ClassB instance) with myClass and call onStart() on it.
ClassB would probably contain a List<OnStartListener> which is used in a loop and onStart() is called on each element. Registering would mean assing the instance of ClassB to that list.
Currently i am rewriting a java project by groovy, then i came across this problem
Java:
public abstract class AbstractJavaClass {
private ConfigClass configClass;
public void go();
g/setter
}
public class JavaClass extends AbstractJavaClass {
#Override
public void go() {
do something;
}
}
the ConfigClass member was injected in xml ways
<bean id = 'configClass' class='ConfigClass'></bean>
<bean id = 'javaClass' class='JavaClass'>
<property name='configClass' ref='configClass'/>
</bean>
Groovy:
class GroovyClass extends AbstractJavaClass {
#Override
public void go() {
do something;
}
}
How should i implement the property ref in groovy class?
At last i used this method.
Groovy:
class GroovyClass extends AbstractJavaClass {
public GroovyClass() {
configClass = new ConfigClass();
configClass.setSomeAttributes();
}
#Override
public void go() {
do something;
}
}
I have the following:
public class Notifier{
CustomPlayer mCustomPlayer;
CurrentPlayer mCurrentPlayer;
}
public class MainActivity extends Activity{
public void onCreate(){
Notifier ntf = new Notifier();
if( index == 0){
ntf.mCustomPlayer = new CustomPlayer(this);
}
else{
ntf.mCustomPlayer = new CurrentPlayer(this); // having problem here
}
}
}
In Notifier class, I just want to have one object mCustomPlayer to switch between CustomPlayer and CurrentPlayer in MainActivity class.
I tried adding the following in Notifier class,
public class Notifier{
CustomPlayer mCustomPlayer;
CurrentPlayer mCurrentPlayer;
public Object getType(int index) {
if (index == 1) {
return CurrentPlayer.class;
}
else {
return CustomPlayer.class;
}
}
}
With that I am having a problem when trying to initialize mCustomPlayer in MainActivity class.
ntf.mCustomPlayer = new (ntf.mCustomPlayer)getType(0); // compile error
Is there a way to realize this?
It has been a day since I am trying to configure out the correct implementation.
Should I use Interface in this case?
To use the new keyword you must supply a class (i.e. new MyClass()).
You could use reflection for this... but wouldn't it be much simpler to just have a common superclass (or interface) for CustomPlayer and CurrentPlayer?
For example, suppose both CustomPlayer and CurrentPlayer have the playOne() and playTwo() methods. You could then define:
public interface Player {
void playOne();
void playTwo();
}
public class CurrentPlayer implements Player {
#Override
public void playOne() {
// code
}
#Override
public void playTwo() {
// code
}
}
private class CustomPlayer implements Player {
#Override
public void playOne() {
// code
}
#Override
public void playTwo() {
// code
}
}
public class Notifier {
Player mPlayer;
}
And then assign mPlayer with new CurrentPlayer() or new CustomPlayer() You can then call any methods on the interface.
You could using Reflection:
public class Notifier{
public CommonInterface getInstance(int index, Class<Activity> activity){
Class<?> claz = getType(0);
Constructor<?> cons = claz.getConstructor(activity);
return (CommonInterface) cons.newInstance(this);
//or you could just type cast it manually if you do not wish to use CommonInterface
}
But having a common interface is the right way to go. You dont have to worry about reflection then.
Since you have same function for both the classes so use interface and access the object -
public class MainActivity extends Activity{
interface CurrentPlayer { void game(); }
interface CustomPlayer { void game(); }
interface Player extends CurrentPlayer, CustomPlayer { }
public void onCreate(){
Player swan = new Player() {
#Override
public void game() {
System.out.println("Swan Player"); //Swan Player
}
};
}
}