Какая польза от вызова new на экземпляре объекта?

Я читаю Programming Perl, и я нашел этот фрагмент кода:

sub new {
    my $invocant = shift;
    my $class   = ref($invocant) || $invocant;
    my $self = {
        color  => "bay",
        legs   => 4,
        owner  => undef,
        @_,                 # Override previous attributes
    };
    return bless $self, $class;
}

С конструкторами, подобными этому, какое преимущество вызова new в экземпляре объекта? Я предполагаю, что это за что, да? Я предполагаю, что если кто-то захочет написать такой конструктор, ему придется добавить еще один код, который копирует атрибуты первого объекта в тот, который будет создан.

Ответ 1

Таким образом, вы можете создать другой объект того же класса, не зная, что такое исходный объект класса - это может сделать для некоторого действительно аккуратного компактного шаблона factory.

В качестве примера это полезно, когда у вас есть объекты ресурсов, которые необходимо построить, по мере необходимости, и стоимость вычисления. Какой-то ресурсный объект WHICH высок (скажем, долговременный запрос БД). Таким образом, factory увидит, был ли передан старый объект ресурса, и если да, создайте его так же, как он, просто назовите $old_object->new() - избегая затрат ресурсов на повторное вычисление вида ресурса.

В качестве другого примера, если у вас есть иерархия классов, обозначающая животных, и factory для создания новых животных в симуляции, вы можете называть $newborn = $factory->make_new_animal($mother) с реализацией factory просто $object->new()

Ответ 2

Я не вижу никакой реальной выгоды. Вы всегда можете просто сделать ref($obj)->new или иметь способ сделать $obj->clone; таким образом вам не остается задаться вопросом, какой из этих двух $object->new делает.

Ответ 3

Как говорили другие, он допускает полиморфное создание экземпляра нового объекта без необходимости знать тип этого экземпляра.

Что касается клонирования объектов, я обычно пишу явные методы clone() или copy(), которые могут правильно копировать атрибуты и другие данные, но нет причин, по которым new() не может позаботиться об этой роли, пока это четко зафиксировано. Однако я вижу два преимущества в их определении отдельно:

  • возможность использовать другой класс (дочерний элемент или роль mixin/role (например, роль Moose)) для переопределения различного поведения
  • возможность сделать код более понятным, например, если шаги, необходимые для создания нового "пустого" объекта, сильно отличаются от тех, которые клонируют существующий объект.