Home > Blockchain >  How do I represent static constants that are derived at run time?
How do I represent static constants that are derived at run time?

Time:11-22

I have senderA and senderB both implementing sender and both singletons, and I have a SenderWrapper (which could possibly implement an ISenderWrapper) class where I want to represent SenderA and SenderB as some sort of static constants.

I'm getting the instances, senderA and senderB using Guice at runtime.

I'm creating many instances of the SenderWrapper class in runtime (think one per request) and I want to somehow represent senderA and senderB in these classes. I will be using them in some methods defined in SenderWrapper.

I have a couple of solutions to this:

  1. I have two non static fields senderA and senderB and I pass them from the constructor. (Perhaps I could inject them as well but I'm worried about performance)

  2. I can have static fields for senderA and senderB and set them up in runtime in a Guice module. But the problem is that these fields will not be const and sends the wrong message that it could be changed during runtime.

public class SenderWrapper implements ISenderWrapper {
    
    public static Sender senderA = null;
    public static Sender senderB = null;

    public void dummyMethod() {
        senderA.send(); senderB.send();
    }

}
    
//in Guice module
@Provides
public providesSenderA(){
    Sender senderA = new SenderA();
    SenderWrapper.senderA = senderA;
    return senderA;
}

  1. My current solution is using an Enum class to represent senderA and senderB. Something like
enum Senders {
senderA, senderB
}

I get a feeling that this is similar to the solution mentioned in point 2, at least functionally. I just hate using enums though.

What is the best, most elegant way to go about this situation? I don't mind refactoring, some level of indirection to solve this.

CodePudding user response:

Why not have an Enum (renamed it a bit, so we know it's an enum, not a class) like this:

enum SenderType {
    SENDER_A, SENDER_B
}

And then have your class like this:

public abstract class SenderBase {

    public final SenderType myType;
    
    public SenderBase(SenderType pType) {
        myType = pType;
    }
    
    // optional getter
    public SenderType getType() {
        return myType;
    }
    
    public void send() {
        // here, send myType to socket. 
        // best is to send myType.name(), because ordinal WILL change when you re-order the enums in their enum class.

        // or, if you have different send() implementations for A and B, make this method abstract (and empty, remove body) so you FORCE A and B to implement it.
    }
    
}

and your class implementations like this:

class SenderA extends SenderBase { 
    public SenderA () {
        super(SenderType.SENDER_A);
    }
}

class SenderB extends SenderBase {
    public SenderB () {
        super(SenderType.SENDER_B);
    }
}

and construct via:

SenderA senderA = new SenderA();
SenderB senderB = new SenderB();

and your Wrapper:

public abstract class SenderWrapper {

    public final SenderA mySenderA;
    public final SenderB mySenderB;
    
    public SenderWrapper() {
        mySenderA = new SenderA();
        mySenderB = new SenderB();
    }
    
    public void send() {
        mySenderA.send();
        mySenderB.send();
    }
    
}

actually now that I think about the Wrapper, it might even have an (Array)List where you add all your implementations, and in send() just iterate over them.

CodePudding user response:

The answer turned out to be anonymous class.

In my Guice module, I do this:

//in Guice module
@Provides
public providesSenderWrapper(final SenderA senderA, final SenderA, senderB){
    return new ISenderWrapper {

        @Override
        public Send() {
            senderA.send(); senderB.send();
        }
    }
}

Neat way to have effective constants in the class.

  • Related