CGI/Perl Guide | Learning Center | Forums | Advertise | Login Site Search: in Perl Guide PerlGuru Forums Learning Ctr
 MAIN INDEX SEARCHPOSTS WHO'S ONLINE LOG IN

Home: Perl Programming Help: Beginner:
private and protected methods

 1 2  View All Print Thread

ChopperCharles
Novice

Apr 3, 2012, 7:57 AM

Post #26 of 32 (3825 views)
 Re: [wickedxter] private and protected methods [In reply to] Can't Post
Actually, I tried that last night and that helped some, but for some reason I'm getting undef as the first entry in my array when it's stored in $self. So, inside a hash I'm guessing that since I can add anything at any time, regardless of the fact I'm using strict... that means somehow when I try and clear the array I'm adding an extra undef in? How do I correctly clear and update an existing entry in the hash? Charles. budman User Apr 3, 2012, 8:18 PM Post #27 of 32 (3822 views)  Re: [ChopperCharles] private and protected methods [In reply to] Can't Post You would need to store the values in an anonymous array  Code push @{$self->{"_StructArray"} },  $element; push @{$self->{"_StructArray"} },  @array;  push @{  $self->{"_StructArray"} }, ($e1, $e2, @array); # for array of hashes push @{$self->{"_StructArray"} },  { a=>1, b=>2 };    # or just a hash $self->{"_StructArray"}{a} = 1;$self->{"_StructArray"}{b} = 2;

To access them:

 Code
use Data::Dumper; print  Dumper(  $self->{"_StructArray"} ); print$self->{"_StructArray"}[0];  foreach my $i ( @{$self->{"_StructArray"}  } ) {    print  "$i\n"; } # for array of hashes foreach my$i ( @{  $self->{"_StructArray"} } ) { foreach my$k (sort keys %{$i}) { print "$k  $i->{$k}\n";    } }

Note: When key names start with an underscore, you should quote the key name as it may lead to issues with strict pragma.

I took a look at Class::Struct. My quick guess is that it takes each key you add in the struct method and auto-generates a setter and getter.

 Code
$element_value =$obj->s;           # element value $obj->s('new value'); In order for your object to work like this, you would need to create the setter and getters for each key. This can be done by the AUTOLOAD to create the getter/setter on the fly. Otherwise, it's pretty monotonous. For what it's worth, to save time, headaches, and use proven well tested code - use Moose.  Code sub s { my ($self) = shift;     if (@_) { $self->{'_Struct'}{s} = shift } return$self->{'_Struct'}{s}; } sub t {     my ($self) = shift; if (@_) {$self->{'_Struct'}{t} = shift }     return $self->{'_Struct'}{t}; } These can be pretty repetitive and you notice a pattern. This is the idea behind Class::Struct, you can use AUTOLOAD, or better maybe to build it at compile time using BEGIN. The attributes should be unique, or you can override existing subs.  Code # handle undefined subs package tester; BEGIN { my @attribs = qw(s t u); for my$attrib ( @attribs ) {         no strict 'refs';         # add getter/setter method         *{"$attrib"} = sub { my$self = shift;               if (@_) { $self->{'_Struct'}{$attrib} = shift };               return $self->{'_Struct'}{$attrib};              };     } }   sub new {    my $class = shift; my$self = {};    $self->{'_Struct'} = {}; bless ($self, $class); return$self; } 1;   #!/usr/bin/perl use strict; use warnings; my $k = tester->new();$k->s(1); $k->t(2);$k->u(3); printf "s = %s\nt = %s\nu = %s\n", $k->s,$k->t, $k->u; Output: s = 1 t = 2 u = 3 (This post was edited by budman on Apr 3, 2012, 8:20 PM) budman User Apr 3, 2012, 9:00 PM Post #28 of 32 (3819 views)  Re: [ChopperCharles] private and protected methods [In reply to] Can't Post  Quote Okay, I've changed my code around, but there's still a problem: unless ( (caller)[0]->isa( ref($self) ) ) {
$self->__SetLastError("Access to protected method denied."); return -1; } This doesn't work when the caller is a subclass. If I have class B that inherits from class A,$self will be B, but caller will be A.

Since the subclass is inheriting from the parent, all the methods belong to the subclass, except those methods that are overridden. To access the parents versions, you must use SUPER. Even calling SUPER, as the TacoBell new method does, it still reports the caller as TacoBell.

When I ran a test on the script provided, I see that is the case:

# all the taco bell objects
NEW -> Self: TacoBell Caller: TacoBell
t = TacoBell->new();

Self: Caller: fooBar
__foo -> t->iAmfooBar() success.

Self: TacoBell Caller: main
__foo -> t->__foo("Charles") failed.

Self: TacoBell Caller: TacoBell (this is in the base class)
__foo -> t->burrito() success.

# the foobar objects
NEW -> Self: fooBar Caller: main
f = fooBar->new();

Self: fooBar Caller: main
__foo -> f->__foo("d'oh") failed.

Again, this is all in the perldoc object oriented tutorials.

(This post was edited by budman on Apr 3, 2012, 9:03 PM)

ChopperCharles
Novice

Apr 4, 2012, 8:38 AM

Post #29 of 32 (3803 views)
 Re: [budman] private and protected methods [In reply to] Can't Post
So basically in order for inheritance and protected/private methods to work in a way that is not spaghetti left and right, the base class needs to know the name of all subclasses? That's hardly OO.

As for the other issue with the undef, I figured it out. Thanks.

I have been reading the OO for perl pages, btw.

Charles

budman
User

Apr 4, 2012, 9:13 PM

Post #30 of 32 (3789 views)
 Re: [ChopperCharles] private and protected methods [In reply to] Can't Post
I don't think I follow on the base class needing to know its subclasses.

When TacoBell inherits from foobar, TacoBell extends foobar but its identity is still TacoBell. When you issue, use parent fooBar, this uses fooBar to load its methods into TacoBell's namespace/package, and then pushes fooBar onto @ISA. @ISA is used as a method lookup table, that sets a lookup precedence for method calling. When a method is requested, it searches TacoBell, in case of any overrides, and then fooBar.

Perl doesn't really support "Private" anything. Its all Public. We are using a hack to simulate Private functions. Python has the same issue, but decided to remove any methods from its lookup tables that begin with an underscore. However, this can be bypassed very easily, because even though it may appear to be private, its still public.

In Perl and Python, private is done by convention only. It's up to the programmer to respect this.

Now in Perl 6, there has been requests to add 'private' which will do exactly as you expect. So this may find it's way into Perl 5 as well.

As for Moose, there is an extension that does private and protected modes. But, they are still remain public.

http://lumberjaph.net/perl/2009/06/30/private-and-protected-methods-with-moose.html

Also, there are other ways, using trait and writer attribs in Moose to simulate private.

http://stackoverflow.com/questions/3996503/how-can-i-create-internal-private-moose-object-variables-attributes

(This post was edited by budman on Apr 4, 2012, 9:16 PM)

ChopperCharles
Novice

Apr 6, 2012, 12:17 PM

Post #31 of 32 (3776 views)
 Re: [budman] private and protected methods [In reply to] Can't Post
Inside a method in fooBar:
 Code
unless ( (caller)[0]->isa( ref($self) ) ) {...}$self is fooBar, but caller is TacoBell. Even though caller inherits from fooBar, this will not work. So, inside fooBar I need:
 Code
unless(index(caller[0], "fooBar") != -1 && index(caller[0], "TacoBell") != -1))

eg, if caller is fooBar or caller is tacoBell, we're good.

I don't want to rely on calling conventions. People often mess with things they shouldn't -- The goal here is to make it that much more difficult for someone to do something stupid.

If I could, I'd abandon perl altogether and write it in java or c++, but I'm extending an open source project and I am limited with what resources I can use. I can't even use a later version of perl.

budman
User

Apr 7, 2012, 7:56 AM

Post #32 of 32 (3767 views)
 Re: [ChopperCharles] private and protected methods [In reply to] Can't Post
So you do not want this to be inherited or used by anything else.

 Code
# create a class attribute my @myFriends = ( __PACKAGE__, "TacoBell" );  # change the unless statement in __foo to: ( my $object = (caller)[0] ) =~ s/.*:://; unless ( grep {$object } @myFriends ) {     $m_LastError = "Access to private method denied.$object";     return -1; }

Strange though, @ISA is pretty safe with inheritance.

Experienced Perl programmers have a lot of respect for each others logic and implementations. They know the limitations of the language and respect it and make it work. Just because objects can be accessed, or jail-breaked, or whatever, a majority if not all try to follow the best practice guidelines.

(This post was edited by budman on Apr 7, 2012, 8:05 AM)

 1 2  View All

 Announcements     PerlGuru Announcements Perl Programming Help     Frequently Asked Questions     Beginner     Intermediate     Advanced     Regular Expressions     mod_perl     DBI     Win32 Programming Help Fun With Perl     Perl Quizzes - Learn Perl the Fun Way     Perl Golf     Perl Poetry Need a Custom or Prewritten Perl Program?     I need a program that...     I Need a Programmer for Freelance Work     Throw Down The Gauntlet General Discussions     General Questions     Feedback     Tutorial/Article Suggestions for The Learning Cent     Internet Security Other Programming Languages     Javascript     PHP

 Search this forum this category all forums for All words Any words Whole Phrase (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives