What is the difference in memory usage and reference counting in “has-a” and “is-a” relationship in Perl?

Refresh

December 2018

Views

120 time

1

I read the "Programming Perl" book which is rather complicated in some places. And one of those places is the section "Instance Destructors" in the 12th chapter "Objects". This section says:

  1. Objects in Perl are destroyed when there is no more references to them.
  2. There is an opportunity to capture control just before object is going to be recycled by defining DESTROY method in its class.
  3. Although destructors are rarely needed in Perl, some objects may have, for instance, filehandles or database connections, which are outside of the memory system. So it is necessary to attend them specially.
  4. Perl does not do hierarchical destruction.

Then there is a paragraph which I failed to understand:

This only applies to inherited classes; an object that is simply contained within the current object—as, for example, one value in a larger hash—will be freed and destroyed automatically. This is one reason why containership via mere ag- gregation (sometimes called a “has-a” relationship) is often cleaner and clearer than inheritance (an “is-a” relationship).

I can't understand what it means. Does it mean that an object that IS NOT simply contained within the current object, WILL NOT be freed and destroyed automatically?

I do know that a DESTROY that is called on the garbage collection is the nearest one and only one. No other overridden DESTROY methods are called when there is no refs to an instance. But, as I understand, the same behavior is expected when a ref to an instance is placed inside another object.

Would someone be so pleasant to construe and to provide a code-example ?


UPDATE:

Actually what I was looking for, was the explanation of the This only applies to inherited classes; words which turned out to be that:

If you have an instance of a class and it has a DESTROY method than that method will override DESTROY methods of a parent class(es), but that does not apply to an object, that is in a has-a relationship with the object in question. Its DESTROY won't be overridden

Sorry for not clear question, it would better fit to the English Language and Usage. Thanks to everyone.

4 answers

1

Наследование аа соотношение «является-а» и любой атрибут класса / пакета есть (лоси с ' has«) или хэш - ключи благословенного объекта (предполагается , что объект благословляются в hashref, например) являетсяhas-a

2
  1. В-а имеет отношение, объект часто имеет ссылку на другой объект. Таким образом , данный класс Van, это экземпляр Vanимеет колесо . Когда этот экземпляр будет уничтожен, Perl (программа) будет вызывать деструктор для Wheelобъектов по отдельности, так как они являются двумя отдельными объектами.

  2. В ап-связь, ссылка для Van IS та же ссылка для Vehicleобъекта. Таким образом , это не так, как это делают некоторые языки, шаг по иерархии , призывающей DESTROYвсе унаследованные классов , он просто называет DESTROYодин раз для каждой благословенной ссылки.

Примечание: # 1 не всегда. Например наизнанку объекты не содержат ссылки на подклассы, они благословенные скалярные ссылки, адрес которых используются в качестве ключа в лексической хэш в пакете. Лексической объем упорного пакета содержит ссылку, а не объект. Но это только служит , чтобы сделать это нет прямой корреляции между классом Очисткой и-а / есть-а отношения.

Это по - прежнему ясно , что отдельное уничтожение должно быть сделано, даже несмотря на то что Perl автоматически не пожинать эти есть-а отношения.

Так что я думаю , что ключ к пониманию этого является то , что в России имеет отношения-а, есть отдельная ссылка , которая должна быть уничтожена. Perl либо делает это автоматически , как счетчик ссылок уменьшается, или вы должны сделать это самостоятельно.

1

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

package MyClass;
sub new {
  my $class = shift;
  my $obj = bless {}, $class;
  $obj->{some_thing_else} = SomeOtherClass->new;
}

Это-отношения это другое название для наследования.

package SomeSubClass;
use parent 'SomeParentClass'; 
# older ways to do this are 'use base' and pushing on @ISA.

Там нет ничего особенного об этих понятиях, как это относится к Perl, но я показал примеры Perl выше.

Ваш первый пример просто стандартный класс Perl. Ваш второй пример представляет собой HAS-отношения. Ни один из кода snippts пример наследования (это-а).

[Кстати, при вызове blessв вашем методе new, вы должны получить имя класса из первого параметра новых (как я показал выше), в противном случае, люди не смогут наследовать от вашего класса , не перекрывая new. Если я позвоню SomeSubClass->new, и SomeSubClass унаследовал новый от SomeParentClass и SomeParentClass делает то , что ты только что сделал, то я получить объект класса SomeParentClass вместо SomeSubClass. (Конечно, может быть , вы не хотите , чтобы ваш класс наследуемый, или вы хотите новый , чтобы быть перекрыты, по какой - либо причине.)]

объектная система Perl является очень голые кости, вы можете сделать все, что вы хотите от него. Но сообщество движется к чему-то называется Moose, модуль CPAN, который предлагает более сложную систему объектов, построенный на вершине.

3

Правило 1: Объекты в Perl уничтожаются, когда нет больше ссылок на них.

{
  my $object = Class->new()
}
# there are no more references to $object
# (it is out of scope and can't be accessed by any means)
# Perl is free to garbage-collect it.

Правило 2: Существует возможность захватить контроль непосредственно перед объектом собирается быть утилизированы путем определения УНИЧТОЖИТЬ метод в своем классе.

package Class;
sub new     { return bless({}, shift) }
sub DESTROY { print STDERR "The object is destroyed" }

####

{
  my $object = Class->new();
}
# before the object is garbage-collected, cleanup-operations should be manually performed
# like closing down connections, solving circular references
# any time, the object might print it's message.

Правило 4: Perl не делает иерархическое разрушения.

package AnotherClass;
use Class;
use parent 'Class';
sub DESTROY { print STDERR "subclass reporting dead" }

Теперь , если AnotherClassбудет экземпляр, только DESTROYметод AnotherClass будет называться, неDESTROY метод Class. Это означает , при отсутствии иерархического разрушения. Это очевидно, так как DESTROYметод перезаписывает предыдущую запись. Оригинал DESTROYможно назвать вручную

Использование родительского класса и дочерний класс является-A IS отношения: AnotherClassэто Class.

Если мы имеем YetAnotherClass:

package YetAnotherClass;
use Class;
sub new {return bless({member => Class->new()}, shift) }

{
   my $object = YetAnotherClass->new();
}
# $object goes out of scope (zero reference count) and will be destroyed.
# Therefore, the reference count of the "member" drops to zero
# The member will therefore be destroyed and print it's message.

Это случай агрегации ( Classявляется членом данных YetAnotherClass), и HAS-A отношения.