• Advertisement
Sign in to follow this  

Private class-member variables act like C++'s protected?

This topic is 1142 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Could you please add something to the documentation to clarify the behavior of private base-class-member variables in derived classes? It seems that there's no way to preclude derived classes from accessing a base class' private members? Could the final keyword perhaps be extended for this use-case?

Thank you!

Share this post


Link to post
Share on other sites
Advertisement

-snip- I'm an idiot: didn't see this was AngelCode

Edited by KamilKZ

Share this post


Link to post
Share on other sites

I'll update the manual to clarify the meaning of private members.

Do you really need to prevent a derived class from accessing the base class' member? Can you give a useful example of this so I can consider the worthfullness of implementing it (maybe even change the meaning of 'private' and include 'protected' to be more in line with C++/Java/C# etc).

Share this post


Link to post
Share on other sites
Allowing a child class to access any data in a parent class allows the child to potentially break invariants the parent wants to establish. In particular, under changing requirements the meaning of data in the parent may change, which if always exposed to every child increases the area of the code at risk of breaking from the change. Having an intermediate level allows the parent to control the data and functions it grants the child privileged access to, while continuing to enforce invariants but not exposing too much to the wide world.

I'm not sure this is quite as useful for a "scripting" language than one intended for building large scale systems. However a potential use might be a modding API, where the game engine might provide some helpful parent classes but needs to maintain a certain amount of hidden state / behaviour in the script side - stuff that can be freely changed / removed between versions without breaking client code. Edited by rip-off

Share this post


Link to post
Share on other sites


I'm not sure this is quite as useful for a "scripting" language than one intended for building large scale systems.

 

This is exactly my point. Many of the design decisions I take for AngelScript are based on the fact that it is a script language, and not really meant for large scale standalone programs. I'm not trying to recreate C++ in scripting form. smile.png

 


However a potential use might be a modding API, where the game engine might provide some helpful parent classes but wants to maintain a certain amount of hidden state in the script that can be freely changed between versions without breaking client code.

 

This makes sense.

Share this post


Link to post
Share on other sites
Disclaimer: I don't use AngelScript so I wouldn't advocate implementing anything just for my theoretical use case!

Share this post


Link to post
Share on other sites

Disclaimer: I don't use AngelScript so I wouldn't advocate implementing anything just for my theoretical use case!

You covered my use-case pretty nicely :)

Share this post


Link to post
Share on other sites


Disclaimer: I don't use AngelScript so I wouldn't advocate implementing anything just for my theoretical use case!
Too late, Andreas already implemented all the ideas for all your theoretical cases.

Share this post


Link to post
Share on other sites

I've corrected the meaning of private class properties in revision 2098. Now a derived class cannot access the private properties of the base class,

Share this post


Link to post
Share on other sites

I've corrected the meaning of private class properties in revision 2098. Now a derived class cannot access the private properties of the base class

 

Since this has backwards-compatibility implications, would you consider making this the new default, but adding an engine option to make old behavior an error or to emit a warning?

 

Thanks!

Edited by iraxef

Share this post


Link to post
Share on other sites

I'd rather not if it can be avoided. Keeping backwards compatibility for every little change pollutes the code, which is something that I try to keep at a minimum. Not only does it pollute the code but it also adds additional risks for bugs in the library.

 

Do you have cases of failures without this? Wouldn't it be possible to have the scripts updated (after all it is just a matter of removing the word private from the property declaration)?

Share this post


Link to post
Share on other sites

I wouldn't bother you if the scripts could be updated :)

 

We have use-cases where we want to be able to update the engine to have the latest and greatest features/performance/etc., but our application has to be able to run existing scripts which cannot be changed.

 

I understand your concern - maintaining backwards compatibility for any stretch of time is a huge pain. I'll investigate a local patch. Thank you.

Share this post


Link to post
Share on other sites

I'd have to set it to 'warn' - precisely because there are lots of existing scripts and it wouldn't be feasible for me to 1) run every single codepath of every single script or 2) verify correctness by code inspection.

Share this post


Link to post
Share on other sites

If it just warns but then continue to work as before, then you're missing out on the fix, aren't you? 

 

By the way, what is this application of yours that have lots of existing scripts? I apologize if you've already told me before, I can't keep track of who is developing what rolleyes.gif

Share this post


Link to post
Share on other sites

Yes I would be missing out on that fix, but without the option to miss out on it, I wouldn't be able to update the library past that revision and I'd miss out on everything else.

Share this post


Link to post
Share on other sites

I can imagine a situation where say some game company creates a game that allows users to mod some things via AngelScript. Let's say there's a community of such mods (scripts) out there. Then the game releases an update and for whatever reason (i.e. needed a bug fix) it incorporated a new AngelScript version. If there was a backwards compatibility break, that would mean that users who updated to the new version of the game would not be able to use any of the already-existing mods/scripts.. as those scripts would fail to compile.

 

Maybe starting with a future version (3?) you could commit to supporting backwards compatibility within that major version - that is, any valid script that was created/tested against a version 3 AS would continue to work as long as the application upgraded AS within version 3. Once the application upgraded past version 3 (say to 4), all bets are off. This is how Unity works, for example.

 

Just a thought.

Edited by iraxef

Share this post


Link to post
Share on other sites

The day I commit to 100% backwards compatibility with new versions is the day that I stop evolving the script engine and only do bug fixes. Even so, a bug fix in the compiler might also break something that was apparently working before. I avoid as much as possible making design changes that break backwards compatibility, but I really don't see how to guaranteeing that a bug fix doesn't accidentally break something. 

 

 

Still, you win on the argument on the private members because it is officially documented that they are visible to derived classes. Only because of this will I add an engine property to allow the previous behaviour to be used for those applications that want it (even though it is wrong).

Share this post


Link to post
Share on other sites

One easy-ish solution is to add the "protected" keyword, which is the old behavior. Then people upgrading can just run a replace-all ["private:" with "protected:"] and continue on their way. Or you could introduce a new keyword for the new behavior, "really-truly-private:" leaving the old keyword for the old behavior. "internal:" maybe. But better to be consistent with terminology used in other languages, if possible. But at some point, there will always be source-breaking changes.

 

(I'm not yet an angelscript user, but I read the angelscript threads in this forum alot)

Edited by Servant of the Lord

Share this post


Link to post
Share on other sites


Then people upgrading can just run a replace-all ["private:" with "protected:"]

 

The kind of backwards compatibility I'm talking about means you can't touch previously-written scripts - they have to continue working under the new AS version. If you've got a script which is under development or you're talking about future scripts, of course you'd use the improved/correct syntax :)

Share this post


Link to post
Share on other sites

you can do your search / replace during load time

 

That's tricky.. stuff like

string foo = "this is private";

all of a sudden becomes

string foo = "this is protected";

? smile.png

Edited by iraxef

Share this post


Link to post
Share on other sites

Is the string "private:" (with the colon) used in the script anywhere except in classes? If not, it's a simple find-and-replace.

 

The only thing you want to be careful of is making sure not the replace *new* scripts that are legitimately trying to use 'private' in the new way.

 

You can check the timestamp of the file when loading it, but I don't trust OS-given timestamps.

 

Instead, the easiest way would be to change your file extension. Any file loaded with ".as" extension (or whatever you used to use), automaticly replaces "private:" with "protected:" or "public:" (if protected isn't available). But from now on, new scripts can use ".as1" extension, or another extension of your choice.

 

This all happens seamlessly in your engine without having to hinder new scripts and without modifying old scripts.

Edited by Servant of the Lord

Share this post


Link to post
Share on other sites

The CScriptBuilder add-on can quite easily be modified to automatically change the private keyword for something else. It already has logic to parse scripts to identify class methods and properties (for use with metadata). 

 

Since in your case you already know that the scripts work (i.e. you don't have to worry about scripts having compiler errors before the change) the solution would be to simply change the private keyword to blanks. The properties that are declared as private aren't accessed anyway, otherwise the script wouldn't compile successfully before.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement