After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 690848 - Add support for "protected" class members
Add support for "protected" class members
Status: RESOLVED OBSOLETE
Product: vala
Classification: Core
Component: Genie
unspecified
Other All
: Normal enhancement
: ---
Assigned To: Jamie McCracken
Vala maintainers
Depends on:
Blocks:
 
 
Reported: 2012-12-29 03:03 UTC by Tal Liron
Modified: 2018-05-22 14:39 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Protected class members in Genie (5.88 KB, patch)
2014-12-04 23:41 UTC, Michal Proszek
none Details | Review
Protected class members in Genie v2 (5.89 KB, patch)
2014-12-05 00:09 UTC, Michal Proszek
none Details | Review

Description Tal Liron 2012-12-29 03:03:14 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.
Comment 1 Jamie McCracken 2013-09-08 21:23:30 UTC
protected is not supported in vala

variables that start with underscore are always private. Everything else defaults to public
Comment 2 Jürg Billeter 2013-09-08 21:27:07 UTC
(In reply to comment #1)
> protected is not supported in vala

Support for this has been added a long time ago, see bug 592577.
Comment 3 Jamie McCracken 2013-09-08 21:30:19 UTC
Ok reopening
Comment 4 Michal Proszek 2014-12-04 23:41:14 UTC
Created attachment 292159 [details] [review]
Protected class members in Genie
Comment 5 Michal Proszek 2014-12-05 00:06:03 UTC
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);
 		}
Comment 6 Michal Proszek 2014-12-05 00:09:04 UTC
Created attachment 292162 [details] [review]
Protected class members in Genie v2

Sorry for this ^. My mistake (I thought i can edit a comment).
Comment 7 Luca Bruno 2014-12-06 15:16:10 UTC
You are changing the behavior of all existing genie programs by making _foo being protected instead of private. Use __foo for protected instead.
Comment 8 Al Thomas 2014-12-06 16:30:57 UTC
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.
Comment 9 Luca Bruno 2014-12-06 16:35:04 UTC
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.
Comment 10 Jamie McCracken 2014-12-06 17:22:48 UTC
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
Comment 11 Al Thomas 2014-12-06 17:32:26 UTC
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.
Comment 12 GNOME Infrastructure Team 2018-05-22 14:39:29 UTC
-- 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.