Initializing super class's variable from sub class I have written down codes something like below:

abstract class ZmqSubscriber {
   protected String zmqPort, zmqIp, zmpTopic;
   public void start() {
      init();
      // connect to zeroMQ with initialized zmq port, ip, topic and receive data
   }
   abstract protected void init();
}

abstract class Collector extends ZmqSubscriber {
   @Override
   protected void init() {
      super.zmqIp = this.zmqIp;
      super.zmqPort = this.zmqPort;
      super.zmqTopic = this.zmqTopic;
   }
   public void otherMethod() { //blablabla }
}

class Syncronizer extends ZmqSubscriber() {
   //blablabla
}

class SensorCollector extends Collector {
   private String zmqPort, zmqIp, zmpTopic;
   @Override
   protected void init() {
      //this.zmqIp, this.zmpPort, this.zmqTopic will be already initialized at this moment using Spring framework's xml config file. In this way we can change ip and port at any time
      super.zmqIp = this.zmqIp;
      super.zmqPort = this.zmqPort;
      super.zmqTopic = this.zmqTopic;
      super.init();
   }
   // getters &amp; setters for zmq port, ip, topic
}
class BeconCollector extends Collector {
   // blablabla like SensorCollector
}


I definitely need three-level extends and this code is running well.
But I think the way of initializing super class's (ZmqSubscriber) instance variable (zmqPort, zmqIp, zmqTopic) in sub class (SensorCollector) is not elegant, I can't say exactly why I think the part is not elegant, but I'm just "Feeling" it's not right when I looking at the code, maybe it is because of the duplicated code in init() method...

Could anyone suggest more elegant architecture?
It is ok to have more than two layers if you have a good reason for it. But, because the code shows only a little part, you probably have other subclasses of ZmqSubscriber.



In SensorCollector you are hiding variables by defining new variables with the same name. This leads to a bad bug which is difficult to hunt down. In case you set the local variables and calling a method of the parent class, this method doesn't use the values of your local variables, so the method doesn't behaves like you would expect, but it is not the method's fault. You probably shouldn't hide the parent's variables.



In Collector.init() you assign a variable to itself, so those three assigns don't do anything.

Here a little prove. Note: I compare super.a and this.a with == to show that their reference are equal, which means they occupy the same memory.

class Parent { String a = "foobar"; }

class Sub extends Parent {
    Sub() { System.out.println(super.a == this.a); }

    public static void main(String[] args) {
        new Sub();
    }
}




I think init()-methods in general are doing the same job a constructor does. So in my opinion you should use constructors instead. If you cannot use a constructor have a look at the builder pattern.

This is my suggestion using constructors. I defined the variables of ZmqSubscriber as final because I think they should never change in the lifetime of the object. So you only have getters or you can make them public (but this is very controversial, depends on your coding standards).

abstract class ZmqSubscriber {
   protected final String zmqPort, zmqIp, zmpTopic;
   public ZmqSubscriber(String zmqPort, String zmqIp, String zmpTopic) {
      this.zmqIp = zmqIp;
      this.zmqPort = zmqPort;
      this.zmqTopic = zmqTopic;
   }
   public void start() {
      // connect to zeroMQ with initialized zmq port, ip, topic and receive data
   }
   // getters for zmq port, ip, topic
}

abstract class Collector extends ZmqSubscriber {
   public Collector(String zmqPort, String zmqIp, String zmpTopic) {
      super(zmqPort, zmqIp, zmpTopic);
   }
   public void otherMethod() { /*blablabla*/ }
}

class SensorCollector extends Collector {
   public SensorCollector(String zmqPort, String zmqIp, String zmpTopic) {
      super(zmqPort, zmqIp, zmpTopic);
   }
}




Is zmpTopic a typo? Shouldn't it be zmqTopic?