копирование поля за полем в конструкторе - мне нужна более краткая форма - PullRequest
0 голосов
/ 24 апреля 2019

Я пытаюсь написать конструктор, который создает экземпляр класса из уже существующего экземпляра суперкласса;Я знаю об агрегации - я мог бы создать поле типа MyClass - но я не хочу его использовать.Так что я делаю по очереди каждое поле и инициализирую его, как показано ниже:

public MyClassExtension extends MyClass
{
    Object new_field;

    public MyClassExtension(MyClass instance) 
    {
        this.field_1 = instance.field_1;
        this.field_2 = instance.field_2;

            ......
        this.field_20= instance.field_20;

        this.new_field= some_value;
    }
}

Проблема в том, что этот подход довольно многословен. Есть ли более короткая форма достижения того же самого результата?

Попытки :

  • вызов super(instance) дает 'конструктор не определен' ошибка;действительно, такого конструктора не существует;даже если бы я его создал, тот же вопрос применим к этому конструктору

  • вызов this(instance) дает 'рекурсивный вызов конструктора' ошибка, что нормально, так как явызов метода изнутри самого себя без условия остановки

Контекстная информация: MyClass представляет собой javax.persistence.Entity, таким образом, большое количество полей.MyClassExtension добавляет некоторые логические значения, которые хранят видимость элементов пользовательского интерфейса, в зависимости от данных.

Примечание. Я вынужден использовать этот подход в стеке технологий.До EL 2.2 я не могу вызвать метод бэкэнда из JSF, чтобы определить видимость элемента пользовательского интерфейса.см .: Как вызвать метод с параметром в JSF

РЕДАКТИРОВАТЬ: Я прочитал Копировать конструктор, используя отражение , но ни один из ответов не подходит для меня:

  • первый ответ: я не могу ввести внешнюю библиотеку в существующий проект без согласия моего менеджера;Мне нужен ядро ​​Java функциональность

  • второй ответ: я уже пробовал super() - см. Выше - я не буду дублировать свое объяснение

1 Ответ

0 голосов
/ 24 апреля 2019

Что вы можете сделать, это:

public MyClassExtension(MyClass instance) {
    super(...);
    new_field = some_value;
}

При создании дочернего класса рекомендуется вызывать супер-конструктор (иначе супер-конструктор по умолчанию будет вызываться по умолчанию).

Почему так? Потому что это ограничивает количество раз, когда вам нужно переопределить одну и ту же инициализацию. Например, когда вы хотите создать объект со значениями по умолчанию. Вы делаете это только один раз, в родительском классе и вызываете по умолчанию супер-конструктор по умолчанию при создании подклассов. Вы также можете переопределить значения по умолчанию в подклассах, в зависимости от того, как вы определили свой класс.

Вот пример: при условии, что MyClass определен следующим образом:

class MyClass {
    protected Object field1;
    protected Object field2;
    protected Object field3;

    public MyClass(MyClass c) {
        field1 = c.field1; // Remark: this is only the setup of
        field2 = c.field2; // the reference. If you want to create a
        field3 = c.field3; // copy, please do so with a constructor.
    }

    public MyClass(Object field1, Object field2, object field3) {
        this.field1 = field1; // Same remark here
        this.field2 = field2; // (about references).
        this.field3 = field3;
    }
}

Здесь вы видите, что MyClass имеет 2 определенных конструктора: так называемый конструктор копирования, который принимает объект MyClass в качестве параметра, и конструктор со всеми необходимыми полями.

Затем, когда вы хотите создать подкласс с объектом MyClass в качестве параметра, вы можете сделать это:

class MyClassExtension extends MyClass {
    private Object newField;

    public MyClassExtension(MyClass c, Object newField) {
        super(c);
        this.newField = newField;
    }
}

Но вы также можете сделать это:

class MyClassExtension {
    private Object newField;

    public MyClassExtension(MyClass c, Object newField) {
        super(c.field1, c.field2, c.field3);
        this.newField = newField;
    }
}

Следовательно, вы ограничиваете количество обращений параметром объекта MyClass, а конструктор подкласса MyClassExtension является кратким.

Обратите внимание , что вам нужно предоставить этот код в том или ином месте в вашей программе. Вы должны определить своему компилятору, как создать MyClassExtension с учетом MyClass объекта. Либо код находится в MyClass, либо оба в MyClass и MyClassExtension. Я только предоставляю способ уменьшить кодовую базу и ограничить количество необходимых изменений, если вы хотите что-то изменить в своем коде. С этим решением, если вы измените конструктор MyClass, это повлияет и на MyClassExtension (если вы не введете что-то другое).

Также обратите внимание , что вам нужно определить свои конструкторы копирования самостоятельно, потому что в противном случае компилятор просто не будет знать, хотите ли вы deep copy или просто reference копия. Больше информации здесь http://blog.amitinside.com/Copy-Constructor-in-Java/

...