> -----Original Message-----
> From: John Siracusa [mailto:[EMAIL PROTECTED]
> Sent: Monday, 19 April, 2004 02:21 PM
> To: Perl 6 Language
> Subject: A12: default accessors and encapsulation
>
>
> Let's say I have a class with some attributes:
>
>     class Dog;
>
>     has $.name is rw;
>     has $.age is rw;
>     has $.gender is rw;
>
> I initially decide to accept the default accessors.
>
>     $dog.name = 'Ralph';
>     print $dog.age;
>
> This works well for a while, but then I decide to update Dog so
> that setting
> the name also sets the gender.
>
>     $dog.name = 'Susie'; # also sets $dog.gender to 'female'
>
> How do I write such a name() method?  Do I just check the arg, set the
> gender, and then return $.name as an "lvalue" or something?

class Afghan
        is Dog
{
        does Hunter;
        does AKC;

        has $.name is rw
                will STORE { .set_name($^name); };

        has $.taliban is OppressiveGovernment;

        method set_name($self: String $name) {
                DESTROY unless $.taliban.approves($name);

                given ($name) {
                        when <Names::Female> {
                                ...
                        }

                        ...
                }
        }
}


>
> If so, what happens if, some time down the road, the $.name attribute goes
> away entirely?  I can't return it as an lvalue now, can I?

        method name(String ?$name) {...}

>
> Basically, I'm wondering how much of the object's internals I'm
> exposing by accepting the default accessors.

Since lvalue subs/methods are easy, and $obj.attr looks like $obj.method
with no args, it should be pretty trivial to drop in a replacement if you
decide you don't like the attribute-based solution.

You are a little committed, since <$dog.name = "fred"> does assume that
you've got a reference to something you can pass back, but that's about it.

You can leave the "name" attribute around as a placeholder and let the STORE
block update the "official" location, or you could return some sort of
proxy-lvalue object that wasn't really a part of Dog:

class WeaselDog
        is Dog
{
        class PhonyAttr
        {
                $.store;
                $.fetch;

                method STORE { $.store($^value); return $_; }
                method FETCH { return $.fetch(); }
        }

        method set_name(String $name) {...}
        method get_name() {...}

        method name is rw {
                return new PhonyAttr(
                        object => $_,
                        store => { .set_name $^name; },
                        fetch => { .get_name; }
                );
        }
}


=Austin

Reply via email to