Search code examples
javainheritancesubclasssuperclasscloudsim

The program won't work using subclass instead of superclass


There is a class named Datacenter in which constructor is:

public Datacenter(
        String name,
        DatacenterCharacteristics characteristics,
        VmAllocationPolicy vmAllocationPolicy,
        List<Storage> storageList,
        double schedulingInterval) throws Exception {
    super(name);

    setCharacteristics(characteristics);
    setVmAllocationPolicy(vmAllocationPolicy);
    setLastProcessTime(0.0);
    setStorageList(storageList);
    setVmList(new ArrayList<Vm>());
    setSchedulingInterval(schedulingInterval);

    for (Host host : getCharacteristics().getHostList()) {
        host.setDatacenter(this);
    }

    // If this resource doesn't have any PEs then no useful at all
    if (getCharacteristics().getNumberOfPes() == 0) {
                throw new Exception(super.getName()
                    + " : Error - this entity has no PEs. Therefore, can't process any Cloudlets.");
    }

    // stores id of this class
    getCharacteristics().setId(super.getId());
}

We use this class to make Datacenters in program:

private static Datacenter createDatacenter(String name, LinkedList myHarddriveList, double timeZone) {

    /* Additional codes like defining Hots */

    Datacenter datacenter = null;
    try {
        datacenter = new Datacenter(name, characteristics, 
                            new VmAllocationPolicySimple(hostList), myHarddriveList, 0);
    } catch (Exception e) {
                System.out.println("Error: " + e);
    }

    return datacenter;
}

The result of running program is like that:

enter image description here

The problem is that if I define my own Datacenter by extending Datacenter class the program won't work. I define MyDatacenter class as following:

public class MyDatacenter extends Datacenter{

    /* My own variables */

    public MyDatacenter(String name, 
           DatacenterCharacteristics characteristics, 
           VmAllocationPolicy vmAllocationPolicy,
           List<Storage> storageList, 
           double schedulingInterval) throws Exception {
        super(name, 
                characteristics, 
                vmAllocationPolicy,
                storageList, 
                schedulingInterval);
    }

    /* My own mwthods */

}

So if I change the return type of createDatacenter() method from Datacenter to MyDatacenter the program wont work.

private static MyDatacenter createDatacenter(String name, LinkedList myHarddriveList, double timeZone) {

    /* No changes */

    MyDatacenter datacenter = null;
    try {
        datacenter = new MyDatacenter(name, characteristics, 
                            new VmAllocationPolicySimple(hostList), myHarddriveList, 0);
    } catch (Exception e) {
                System.out.println("Error: " + e);
    }

    return datacenter;
}

No cloudlet will be assigned to any datacenter:

enter image description here

I can not even cast the created Datacenter instance to MyDatacenter.


Solution

  • As per the comments on your question the problem seemed to be you overriding methods like setCharacteristics(...), setSchedulingInterval(...) etc. and calling those methods in the super constructor.

    Without knowing much more about what your system is doing and how overriding those methods affects the inner workings of your application it's hard to give an exact example of the problems you could face. Thus I'll try to provide a more abstract example and hope that I can convey the idea of what could go wrong.

    Let's say we have the following classes:

    class SuperType {
      protected String name;
    
      public SuperType(String n) {
        setName( n );
      }
    
      protected void setName( String n ) {
        name = n;
      }    
    }
    
    class SubType extends SuperType {
      // setting 'id' happens here
      private int id = new Random().nextInt() + 1;
    
      {
        // initializer block, setting 'id' could happen here       
      }
    
      public SubType( String n ) {
        super( n ); 
        // setting 'id' could happen here as well
      }
    
      @Override
      protected void setName( String n ) {
        name = n + " " + id;
      }    
    }
    

    As you can see SubType overrides the method setName(...) that's used in the SuperType constructor. Why is that a problem?

    Consider the order in which initialization happens when we call new SubType("some name"):

    • The constructor SubType(...) calls the super constructor, i.e. SuperType(...)
    • Before the constructor is executed the instance will be created and initialized.
      This happens in the following order for each class in the hierarchy from top to bottom (super to sub types)
      • fields in the order they're listed
      • initializer blocks in the order they're listed
      • constructor

    Thus we have the following execution order in our example (I'll leave Object and non-existant initializations for simplicity)

    • SuperType(...) constructor (because there's no initializer block)
    • setName(...) is being called but that's the overridden version
    • SubType fields are initialized, setting id to a random number
    • SubType intializer blocks run
    • SubType(...) constructor runs

    As you can see, the overridden setName(...) is executed before id is initialized so all that method will see will be its default value (0 for primitive int). And depending on your application that could be the problem - the overridden method might rely on some of the additional variables being initialized properly (e.g. not null) and if that doesn't happen the instances might still be created but not be usable from your application's point of view.