GNOME Bugzilla – Bug 690848
Add support for "protected" class members
Last modified: 2018-05-22 14:39:29 UTC
It seems that Genie only allows for private or public members. Protected access would be very useful for inheritance. On that note -- it doesn't seem possible to define access on members unless they are "prop" or "def". For example: public _my_var: int ...will not work.
protected is not supported in vala variables that start with underscore are always private. Everything else defaults to public
(In reply to comment #1) > protected is not supported in vala Support for this has been added a long time ago, see bug 592577.
Ok reopening
Created attachment 292159 [details] [review] Protected class members in Genie
Comment on attachment 292159 [details] [review] Protected class members in Genie diff --git a/vala/valagenieparser.vala b/vala/valagenieparser.vala index 7abd943..e77bd7b 100644 --- a/vala/valagenieparser.vala +++ b/vala/valagenieparser.vala @@ -67,8 +67,9 @@ public class Vala.Genie.Parser : CodeVisitor { STATIC = 1 << 6, VIRTUAL = 1 << 7, PRIVATE = 1 << 8, - ASYNC = 1 << 9, - SEALED = 1 << 10 + PROTECTED = 1 << 9, + ASYNC = 1 << 10, + SEALED = 1 << 11 } public Parser () { @@ -216,8 +217,10 @@ public class Vala.Genie.Parser : CodeVisitor { } inline SymbolAccessibility get_access (string s) { - if (s[0] == '_') { + if (s.has_prefix("__")) { return SymbolAccessibility.PRIVATE; + } else if (s[0] == '_') { + return SymbolAccessibility.PROTECTED; } return SymbolAccessibility.PUBLIC; @@ -276,6 +279,7 @@ public class Vala.Genie.Parser : CodeVisitor { case TokenType.PASS: case TokenType.PRINT: case TokenType.PRIVATE: + case TokenType.PROTECTED: case TokenType.PROP: case TokenType.RAISE: case TokenType.RAISES: @@ -2642,10 +2646,15 @@ public class Vala.Genie.Parser : CodeVisitor { if (ModifierFlags.PRIVATE in flags) { cl.access = SymbolAccessibility.PRIVATE; + } else if (ModifierFlags.PROTECTED in flags) { + cl.access = SymbolAccessibility.PROTECTED; } else { - /* class must always be Public unless its name starts with underscore */ - if (sym.name[0] == '_') { + /* class must always be Public unless its name starts with + * underscore (protected) or doubleunderscore (private)*/ + if (sym.name.has_prefix("__")) { cl.access = SymbolAccessibility.PRIVATE; + } else if (sym.name[0] == '_') { + cl.access = SymbolAccessibility.PROTECTED; } else { cl.access = SymbolAccessibility.PUBLIC; } @@ -2810,6 +2819,8 @@ public class Vala.Genie.Parser : CodeVisitor { if (ModifierFlags.PRIVATE in flags) { f.access = SymbolAccessibility.PRIVATE; + } else if (ModifierFlags.PROTECTED in flags) { + f.access = SymbolAccessibility.PROTECTED; } else { f.access = get_access (id); } @@ -2922,6 +2933,8 @@ public class Vala.Genie.Parser : CodeVisitor { var method = new Method (id, type, get_src (begin), comment); if (ModifierFlags.PRIVATE in flags) { method.access = SymbolAccessibility.PRIVATE; + } else if (ModifierFlags.PROTECTED in flags) { + method.access = SymbolAccessibility.PROTECTED; } else { method.access = get_access (id); } @@ -3059,6 +3072,8 @@ public class Vala.Genie.Parser : CodeVisitor { var prop = new Property (id, type, null, null, get_src (begin), comment); if (ModifierFlags.PRIVATE in flags) { prop.access = SymbolAccessibility.PRIVATE; + } else if (ModifierFlags.PROTECTED in flags) { + prop.access = SymbolAccessibility.PROTECTED; } else { prop.access = get_access (id); } @@ -3175,7 +3190,7 @@ public class Vala.Genie.Parser : CodeVisitor { if (needs_var) { /* automatic property accessor body generation */ var variable_type = prop.property_type.copy (); - prop.field = new Field ("_%s".printf (prop.name), variable_type, prop.initializer, prop.source_reference); + prop.field = new Field ("__%s".printf (prop.name), variable_type, prop.initializer, prop.source_reference); prop.field.access = SymbolAccessibility.PRIVATE; prop.field.binding = prop.binding; } @@ -3213,6 +3228,8 @@ public class Vala.Genie.Parser : CodeVisitor { var sig = new Vala.Signal (id, type, get_src (begin), comment); if (ModifierFlags.PRIVATE in flags) { sig.access = SymbolAccessibility.PRIVATE; + } else if (ModifierFlags.PROTECTED in flags) { + sig.access = SymbolAccessibility.PROTECTED; } else { sig.access = get_access (id); } @@ -3284,6 +3301,8 @@ public class Vala.Genie.Parser : CodeVisitor { var st = new Struct (sym.name, get_src (begin), comment); if (ModifierFlags.PRIVATE in flags) { st.access = SymbolAccessibility.PRIVATE; + } else if (ModifierFlags.PROTECTED in flags) { + st.access = SymbolAccessibility.PROTECTED; } else { st.access = get_access (sym.name); } @@ -3346,6 +3365,8 @@ public class Vala.Genie.Parser : CodeVisitor { var iface = new Interface (sym.name, get_src (begin), comment); if (ModifierFlags.PRIVATE in flags) { iface.access = SymbolAccessibility.PRIVATE; + } else if (ModifierFlags.PROTECTED in flags) { + iface.access = SymbolAccessibility.PROTECTED; } else { iface.access = get_access (sym.name); } @@ -3414,6 +3435,8 @@ public class Vala.Genie.Parser : CodeVisitor { var en = new Enum (sym.name, get_src (begin), comment); if (ModifierFlags.PRIVATE in flags) { en.access = SymbolAccessibility.PRIVATE; + } else if (ModifierFlags.PROTECTED in flags) { + en.access = SymbolAccessibility.PROTECTED; } else { en.access = get_access (sym.name); } @@ -3472,6 +3495,8 @@ public class Vala.Genie.Parser : CodeVisitor { var ed = new ErrorDomain (sym.name, get_src (begin), comment); if (ModifierFlags.PRIVATE in flags) { ed.access = SymbolAccessibility.PRIVATE; + } else if (ModifierFlags.PROTECTED in flags) { + ed.access = SymbolAccessibility.PROTECTED; } else { ed.access = get_access (sym.name); } @@ -3540,6 +3565,11 @@ public class Vala.Genie.Parser : CodeVisitor { next (); flags |= ModifierFlags.PRIVATE; break; + + case TokenType.PROTECTED: + next (); + flags |= ModifierFlags.PROTECTED; + break; default: return flags; @@ -3595,6 +3625,10 @@ public class Vala.Genie.Parser : CodeVisitor { next (); flags |= ModifierFlags.PRIVATE; break; + case TokenType.PROTECTED: + next (); + flags |= ModifierFlags.PROTECTED; + break; default: return flags; } @@ -3738,6 +3772,8 @@ public class Vala.Genie.Parser : CodeVisitor { if (ModifierFlags.PRIVATE in flags) { d.access = SymbolAccessibility.PRIVATE; + } else if (ModifierFlags.PROTECTED in flags) { + d.access = SymbolAccessibility.PROTECTED; } else { d.access = get_access (sym.name); }
Created attachment 292162 [details] [review] Protected class members in Genie v2 Sorry for this ^. My mistake (I thought i can edit a comment).
You are changing the behavior of all existing genie programs by making _foo being protected instead of private. Use __foo for protected instead.
Personally I would say don't use the double underscore at all and stick with the explicit keyword 'protected'. Genie class properties and methods are public by default. The underscore is a shorthand for making one of these private and should remain that way for backwards compatibility. The double underscore, although convenient for the typist, can be hard to distinguish from a single underscore on first reading. Given that 'protected' is often used to define the extension points of a class it is better to make this explicit with the 'protected' keyword. There are also a number of issues about whether nested classes, enums, structs, fields, signals, delegates, interfaces and error domains can be protected or even private. Finally I'm slightly uneasy that ASYNC and SEALED have changed their position in the ModifierFlags enum.
The underscores is due to python conventions. Except that python uses __ for private. Since genie is born for python-like syntax, I'd not use private and protected keyword, otherwise just use Vala.
I dont think there is a python convention or support for protected status so maybe best to leave it as using the "protected" keyword Double underscore is still considered private under existing genie code so could potentially break something if that was introduced
Ok looks like Jamie has adjudicated as I was writing the below. A few more details if anyone is interested: Hmmm, the underscore seems more Boo like - see http://boo.codehaus.org/Part+08+-+Classes I had to highlight that underscore in your comment because of the web browser font to make sure it was a double underscore and that is my reason the double underscore should be avoided. Python doesn't have private variables as such (see https://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references ) and that is where the double underscore name mangling convention comes in. Similar to single and double underscores used in PHP before object oriented PHP5. Even the Python style guides limits the use of double underscore (https://www.python.org/dev/peps/pep-0008/#method-names-and-instance-variables): "Generally, double leading underscores should be used only to avoid name conflicts with attributes in classes designed to be subclassed. Note: there is some controversy about the use of __names (see below)." Genie also recognises the private keyword: init var aa = new test() print( aa.a.to_string ()) class test: Object prop private a:int = 1 will produce the expected compiler warning. This is why I said the single underscore was a shorthand. In terms of object oriented class design protected relates only to sub-typing. So I think it is of limited use, given design ideas based on SOLID principles, such as Liskov substitution and favouring composition over inheritance. You may want to take a look at how the some in the PHP community used protected when developing the Symfony framework - http://fabien.potencier.org/article/47/pragmatism-over-theory-protected-vs-private As to 'just use Vala' :-) Well, I personally use Genie to avoid superfluous squiggly braces and semi-colons, but that made me smile.
-- GitLab Migration Automatic Message -- This bug has been migrated to GNOME's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/vala/issues/346.