-
Notifications
You must be signed in to change notification settings - Fork 19
Slot Attributes
Please see the main page of the repo for the actual RFC. As it states there:
Anything in the Wiki should be considered "rough drafts."
Click here to provide feedback.
Instance data for classes are in "slots." Slots are declare by: has $var;
.
Note Other types such as has @var
or has %var
might come later. They're not in this proposal because it's unclear what has @var :reader :writer;
means. Does it accept and return lists? It's also required in the constructor in that version. Does it then require an array reference? Due to the flattening nature of some variables in Perl, I'd rather punt on this for the time being.
The variable is the slot and only the slot. The has
keyword does not create any readers, writers, have anything to with the constructors, and so on. It only declares the slot. It's the attributes which handle everything else.
has $x;
is a private slot. Absent other attributes modifying it, it is:
- Read-write (internally)
- Forbidden in the constructor
- Has no public reader or writer
has $x = $value;
supplies a default value. See also :builder
below.
Attributes are for object construction and data modification, and helpers ("nice to haves" which make working with objects more pleasant).
Slots are defined via has $varname;
. This does nothing outside of declaring the slot. Nothing at all. Instead, if we wish to specify arguments for the constructor, we use the :new
syntax.
has $name :new;
If you wish the slot to be allowed to be passed in the constructor, but not required, you must provide default values, or a builder.
has $name :new = 'Ovid';
The default value, of course, may also be undef
if you do not need a value for that slot.
The "name" of a slot is the identifier name of the slot variable. Thus, the name of has $person :new;
is person
. If you need it passed to the constructor with a different name, use the :name(...)
attribute:
has $person :new :name(employee);
Absent a :new
attribute, the attribute must not be passed to the constructor.
Attribute | Meaning | Notes |
---|---|---|
:reader , :reader($name)
|
Creates a read-only public method for the data | N/A |
:writer , :writer($name)
|
Creates a public method (set_$name ) for modifying the data |
This is frequently a code smell |
:predicate , :predicate($name)
|
Creates a has_$name boolean predicate |
What's the difference between uninitialized and undef ? |
:handles(@list|%kv_pairs) |
Delegates the methods to the object in this slot | Requires an object! |
:name($identifier) |
Public name of slot | You cannot use :name on a multi-slot declaration |
The writer creates a method called set_$name
to avoid overloading the
meaning of the method name, and will return the invocant. Setting
:reader($name)
and :writer($name)
to the same $name
would be an error.
This is in part because Corinna would need to special case that and have to write
more complicated internal code.
See Custom Writers for more explanation.
(Arguably, the :writer
attribute could go here)
Attribute | Meaning | Notes |
---|---|---|
:builder , :builder($name)
|
Creates a lazy builder for the slot. | Conflicts: :new
|
:weak |
Weakens the variable in the slot | N/A |
:clearer |
Clears the slots. Sets it to undef if no default value |
Makes no sense without :reader ? |
:immediate |
Slot value is not lazy | Only meaningful with a :builder
|
The above seems to simplify this work quite a bit. Assuming :writer
to be a code smell, the following are "valid" combinations that are likely to be seen.
Note that all of these allow the `:name(identifier) attribute.
Declaration | Constructor | Attribute |
---|---|---|
has $x; | No | No |
has $x :reader; | No | Yes |
has $x :new; | Yes | No |
has $x; | No | No |
has $x :reader :clearer; | No | Yes |
has $x :reader :new; | Yes | Yes |
has $x :reader ; | No | Yes |
has $x :builder ; | No | No |
has $x = $default; | No | No |
has $x :reader :new :clearer; | Yes | Yes |
has $x :reader :clearer; | No | Yes |
has $x :reader :builder ; | No | Yes |
has $x :reader = $default; | No | Yes |
has $x :builder :immediate; | No | No |
has $x :immediate = $default; | No | No |
has $x :reader :builder :clearer; | No | Yes |
has $x :reader :builder :immediate; | No | Yes |
has $x :reader :clearer = $default; | No | Yes |
has $x :reader :immediate = $default; | No | Yes |
has $x :reader :builder :immediate :clearer; | No | Yes |
has $x :reader :immediate :clearer = $default; | No | Yes |
We're working hard to ensure that you can't create an illegal set of attributes for a slot, but we still have a few).
-
:builder
and= $default
-
:builder
or= $default
with:new
-
:immediate
without:builder
; -
:clearer
without:reader
(do we really care about this?)
Corinna—Bringing Modern OO to Perl