iamprerit
iamprerit

Reputation: 41

How to create multiple instances to an implementation of an interface?

Let A be an interface which has a method a. Let B be a class which implements A and has method a and has three fields 1,2,3. I want to use two instances of A (meaning B), both of which have different values of 1,2,3 (present in cfg file) at two different places.

Can someone provide a simple and elegant solution to this problem using Guice.

Upvotes: 2

Views: 835

Answers (2)

mhaligowski
mhaligowski

Reputation: 2222

You don't tell how the class that uses your dependency references the interface. I assume that you want to reference it with an interface.

What you can use, is annotation that will denote which instance you want to use. Assume that these are your implementations:

interface A {
    void a();
}

class B implements A {
    private int value;

    void a() { ... }

    B(int value) { this.value = value; }
}

And these are the classes that use the implementations:

class UserFirst {

    private A a;

    @Inject
    UserFirst(@Named("first") A a) { this.a = a; }
}

class UserSecond {

    private A a;

    @Inject
    UserSecond(@Named("second") A a) { this.a = a; }
}

The thing that decides which implementation is going to be injected is the @Named annotation. You can also define your annotations, but usually it's an overkill.

Now, in order to bind that, you can do something like this:

class MyModule extends AbstractModule {
    @Override
    protected void configure() {

    A first = new B(1);
    B second = new B(2);


    bind(A.class)
        .annotatedWith(Names.named("first")).toInstance(first);

    bind(A.class)
        .annotatedWith(Names.named("second")).toInstance(second);
    }
}

Here's the full documentation: https://github.com/google/guice/wiki/BindingAnnotations

Upvotes: 2

RakNoel
RakNoel

Reputation: 59

if I do understand you correctly, you might want to make B abstract so that you can override the methods which you want to change, if this is the case.

Now I can only assume that by fields you mean field-varriables. I would then recommend you to make them NON-static and change them in the constructor when you make an object. Then read the values of 1,2,3 in the public static void main method and send them upon creating a new object:

public class B implements A {
    private int x,y,z;

    /**
    * This would now be the constructror
    */
    public B(int x, int y, int z){
        this.x = x;
        this.y = y;
        this.z = z;
    }

    /**
    * Then some return functions
    */
    public get1() { return this.x; }
    public get2() { return this.y; }
    public get3() { return this.z; }

    /**
    * Then whatever methods you get from A
    */
    public int someMethodFromA(int x, int y){
        return x*y;
    }
}


public static void main(String[] args) {
    /**
    * Some random method to read inn from CFG file
    */

    int x1 = readXFromCFG();
    int y1 = readYFromCFG();
    int z1 = readZFromCFG();

    B objectB1 = new B(x1,y1,z1);

    int x2 = readXFromCFG();
    int y2 = readYFromCFG();
    int z2 = readZFromCFG();

    B objectB2 = new B(x2,y2,z2);

    int x3 = readXFromCFG();
    int y3 = readYFromCFG();
    int z3 = readZFromCFG();

    B objectB3 = new B(x3,y3,z3);
}

Upvotes: 1

Related Questions