in reply to Re: Perl OOP
in thread Perl OOP

Thanks for the reply! In the case of the #1, when creating immutable objects, it's good practice to prohibit inheritance.

Replies are listed 'Best First'.
Re^3: Perl OOP
by Marshall (Canon) on Jul 05, 2017 at 03:43 UTC
    AFIK, there is no such thing as an "immutable object" (an object where the parameters cannot be modified) in Perl. Perhaps there is such a thing in Java or C#. I don't think such a thing exists in C++. Perl is not Java, C# or C++. I guess if you have an object with 'name' as a property when that object was created, just don't expose set_name() in the public interface? If there is no function to change something, and you "play by the rules", then you can't change it. However there are ways in Perl to circumvent any rule and wind up with obscure code that changes a parameter that is not part of the public interface. I think that is also true in C++. My experience with Java is limited and experience with C# non-existent.

    I perhaps don't understand your question, but if you want an object which can be created but not modified after its creation... just don't expose any "set" functions for parameters within that object - set all of the params in the "new" method. Nothing in Perl that I know of will prevent you from inheriting from such an object.

    I would think that normally your object should have a "has a" relationship to an immutable object rather than your object being an "is a" relationship to said object. Perl will allow you to do something stupid.

      Nothing in Perl that I know of will prevent you from inheriting from such an object.

      Ehhh… it's actually pretty easy to do in Moose/Moo/Class::Tiny. I mean, it's not rocket science to work around, but this should do the job:

      use v5.16; package Example::Phone { use Moo; has number => (is => 'ro', required => 1); sub call { ... } # Make final sub BUILD { my $self = shift; die(sprintf '%s is final; %s cannot inherit', __PACKAGE__, ref +($self)) unless ref($self) eq __PACKAGE__; } } package Example::Phone::Mobile { use Moo; extends 'Example::Phone'; sub send_sms { ... } } my $number1 = Example::Phone->new(number => 1); my $number2 = Example::Phone::Mobile->new(number => 2); # dies

        Ehhhhhhhhhhhhhhh…

        package Example::Phone { use Moo; has number => (is => 'ro', required => 1); sub call { ... } sub BUILD { use MooseX::Final; assert_final( my $self = shift ); } }
Re^3: Perl OOP
by tobyink (Canon) on Jul 05, 2017 at 09:16 UTC

    I don't see why that would be good practice.

    Let's create a telephone class:

    package Example::Phone { use Moo; has number => (is => 'ro', required => 1); sub call { ... } }

    Now let's use it:

    use Example::Phone; my $dad = Example::Phone->new(number => '+44 123 456 7890'); say "Dad's number is ", $dad->number; $dad->call();

    The object is immutable, in that once it's been instantiated, you can't use its public API to alter the number string.

    But that shouldn't stop us from subclassing it:

    package Example::Phone::Mobile { use Moo; extends 'Example::Phone'; sub send_sms { ... } }

    It doesn't in any way compromise the immutability of the parent class.