Программа не будет работать с использованием подкласса вместо суперкласса - PullRequest
0 голосов
/ 18 октября 2019

Существует класс с именем Datacenter, в котором используется конструктор:

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());
}

Мы используем этот класс для создания центров обработки данных в программе:

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;
}

Результат выполнения программы:вот так:

enter image description here

Проблема в том, что, если я определю свой собственный Центр обработки данных путем расширения класса Datacenter, программа не будет работать. Я определяю MyDatacenter class следующим образом:

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 */

}

Поэтому, если я изменю тип возврата метода createDatacenter() с Datacenter на MyDatacenter, программа не будет работать.

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;
}

Ни одно облачное хранилище не будет назначено ни одному датацентру:

enter image description here

Я даже не могу привести созданный экземпляр Datacenter к MyDatacenter.

Ответы [ 2 ]

1 голос
/ 21 октября 2019

Согласно комментариям к вашему вопросу, проблема заключалась в том, что вы переопределяли такие методы, как setCharacteristics(...), setSchedulingInterval(...) и т. Д., И вызывали эти методы в супер-конструкторе. Система работает, и как переопределение этих методов влияет на внутреннюю работу вашего приложения, трудно привести точный пример проблем, с которыми вы можете столкнуться. Поэтому я попытаюсь привести более абстрактный пример и надеюсь, что смогу донести идею о том, что может пойти не так.

Допустим, у нас есть следующие классы:

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;
  }    
}

Как выможно увидеть, что SubType переопределяет метод setName(...), который используется в конструкторе SuperType. Почему это проблема?

Рассмотрим порядок, в котором происходит инициализация, когда мы вызываем new SubType("some name"):

  • Конструктор SubType(...) вызывает супер-конструктор, то есть SuperType(...)
  • Перед выполнением конструктора экземпляр будет создан и инициализирован.
    Это происходит в следующем порядке для каждого класса в иерархии сверху вниз (от супер к подтипам).
    • поля в порядке их перечисления.
    • блоки инициализатора в порядке. они перечислены
    • конструктор

Таким образом, у нас есть следующий порядок выполнения в нашем примере (я оставлю Object и несуществующие инициализации дляпростота)

  • SuperType(...) конструктор (поскольку нет блока инициализации)
  • setName(...) вызывается, но это переопределенная версия
  • SubType поляинициализируется, устанавливая id в случайное число
  • SubType блоки запуска интилизатора
  • SubType(...) запускает конструктор

Как видите, переопределенный setName(...) выполняется до инициализации id, поэтому все, что увидит этот метод, будет иметь значение по умолчанию (0 для примитива int). И в зависимости от вашего приложения это может быть проблемой - переопределенный метод может полагаться на то, что некоторые дополнительные переменные инициализируются должным образом (например, не NULL), и если этого не происходит, экземпляры все еще могут быть созданы, но не могут быть использованы из вашего приложенияточка зрения.

0 голосов
/ 18 октября 2019

Когда у вас есть что-то вроде:

Datacenter d = new MyDatacanter(...);

Единственные методы, доступные d, это те, которые определены в суперклассе Datacenter, если только вы не разыграли d как MyDatacenterобъект:

d.yourCustomMethod(); //won't work
((MyDataCenter) d).yourCustomMethod(); //should work fine
...