Skip to content

Instantly share code, notes, and snippets.

@ZzZombo
Last active November 30, 2016 12:23
Show Gist options
  • Save ZzZombo/34803d3cc640a6fd829b2541b6cdbfc3 to your computer and use it in GitHub Desktop.
Save ZzZombo/34803d3cc640a6fd829b2541b6cdbfc3 to your computer and use it in GitHub Desktop.
class XML::Object
{
protected:
attribute xmlnode;
...
public:
property XML::File file:read;
...
}
class XML::GraphItem : XML::Object
{
private
method set_name(Str:D name)
{
name ne '' ?? xmlnode.setAttribute('name',name) !! xmlnode.removeAttribute('name');
self.name=name;
return self;
}
...
public:
property Str:D name:read,write set_name default='item';
...
}
class XML::GraphItemGroup : XML:GraphItem
{
private
multi method set_count(UInt:D @a)
{
my @b=@a.head(2);
pop @b if @b[0]==@b[1];
if @b>1 || @b[0]!=1
xmlnode.setAttribute('count',join ',',@b);
else
xmlnode.removeAttribute('count');
count=@b;
}
multi method set_count(UInt:D count)
{
set_count [count];
}
...
public
property count:read,write set_count default=1;
...
}
@ZzZombo
Copy link
Author

ZzZombo commented Nov 30, 2016

I'm struggling to implement this class hierarchy in P6 because:

  • Attributes are only private.
  • Private members are inaccessible to subclasses by default, and the suggested workaround is unreasonable: trust each of them by messing with class internals. Due to this, the xmlnode attribute can not be accessed by child classes. I could make it public, but then it means I have to guard against or account for direct changes made on it bypassing the methods of the classes.

If somebody can come up with a way to address this, I'll be eager to listen up.

The current design makes little sense to me, an avid OOP user in many programming languages, maybe that spoiled me beyond recover, but bear with me. Everywhere where there is a built-in or is possible to built your own OOP system, object properties and methods are treated the facade of the underlying black box on equal grounds. But in P6 only methods are allowed to be the facade that you can work with. Attributes are set in stone not to be visible by the outside world, even if sharing such information is desired. You can share it via a method, yes, but that requires 1) a method, and if the basic functionality of autogenerated methods is not enough 2) writing both accessors yourself even if you added only a getter/setter and not both and otherwise the compiler would have added the other itself and you are totally okay with that. You can, yes, you can totally live with only procedural calls to your objects, but under the previous point, the amount of similar code (method get_name { $!name } method get_count { @!count }) you have to write that is more than I'd like to and, frankly, expected before I learned deeper the mechanism of Perl 6 classes. Since attributes are inherently private, and private members in general are completely invisible to anything outside the class, there is no way to share some info with subclasses, like the xmlnode attribute in my example above. I expect from a mature OOP system to handle more than private and public visibility, and absolutely needed addition to this hands down is protected visibility, to share data with subclasses cleanly.

In conclusion, if I made necessary changes to make the code above work in P6, I would have to:

  • Make xmlnode a public attribute.
  • Due to that, handle changes that happen outside the object somehow. Both applicable ways -- deny changes and use only data stored in the object or just read data directly from the node and do not store it in the object anymore -- have drastic consequences I'd rather not to deal with.
  • Write code like the aforementioned method get_name { $!name } (or rather, a pair of multimethods for read and write access to live under the same name of the attribute) for each attribute, since each of them requires a custom setter. Tedious and should be totally unneeded, IMHO.

So all in all, the system has defeated itself, in my view, since the very first point goes against the primal principle of OOP, encapsulation.

The code above is NOT in Perl or any other language, the syntax was created on the fly and only to illustrate what I want to achieve.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment