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:
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:
I can not even cast the created Datacenter
instance to MyDatacenter
.
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")
:
SubType(...)
calls the super constructor, i.e. SuperType(...)
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 versionSubType
fields are initialized, setting id
to a random numberSubType
intializer blocks runSubType(...)
constructor runsAs 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.