I'm writing a class that looks like this:
class ListenSocket is Tap {
has $!VMIO;
has Promise $.socket-host;
has Promise $.socket-port;
method new(&on-close, Mu :$VMIO, Promise :$socket-host, Promise :$socket-port) {
self.bless: :&on-close, :$VMIO, :$socket-host, :$socket-port;
}
submethod BUILD(Mu :$!VMIO) { }
}
When I try to construct the class with defined Promises for $socket-host
and $socket-port
, their attributes in the class end up becoming undefined for whatever reason. What can I do to fix this?
A private attribute provides you a level of protection from the users of your class, for that attribute. If you use a public attribute, you will need to add in more logic to test for invalid values up front, which can be more work, as well as more computationally expensive.
In many object-oriented languages, certain attributes can be declared as private, making it impossible for users of a class to directly view or modify their values. The designer of the class then provides methods to control the ways in which these attributes can be manipulated.
Here in Python, we can make an attribute private by adding 2 underscore characters _ in front of our variable name. Here, instead of using name , we use __name as our variable.
By defining the class members' private , we can protect the data from accidental corruption. The following are the benefits of encapsulation: Protection of data from accidental corruption. Specification of the accessibility of each of the members of a class to the code outside the class.
I should have started off with what Liz wrote. Switch BUILD
to TWEAK
. Then the default BUILD
will do its thing and your socket attributes will get correctly initialized.
The next problem is &on-close
. See Lizmat's answer to Constructors in subclases showing how to deal with that if you can modify the superclass (Tap
in this case) or Jonathan's authoritative answer to Inheriting private attributes in Perl 6 (which is about any access whatsoever to another class's attributes) showing you're out of luck if you can't modify the superclass.
Note that the above two issues aren't really about "private attributes" in a class making "public attributes" undefined. Nor are types relevant.
All attributes are technically private. The private/public distinction is about whether there's a public accessor for a private attribute.
Your custom BUILD
is only initializing $!VMIO
, the one that doesn't have a public accessor. You have neglected to initialize $!socket-host
and $!socket-port
, the attributes that do have public accessors (due to use of the public accessor twigil .
when declaring them).
You presumably wrote a custom BUILD
because the default BUILD
only initializes attributes with public accessors. But if you do that you are taking on full responsibility for object construction and you must initialize all attributes that you want initialized.
It's better to write a TWEAK
. Then you can just deal with the attributes without public accessors. A TWEAK
just adds further initialization to the BUILD
, which for the default BUILD
is just initialization of the attributes with public accessors.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With