Facebook Twitter YouTube Frictional Games | Forum | Privacy Policy | Dev Blog | Dev Wiki | Support | Gametee


Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
AngelScript OO Capabilities - Inheritance
TheGreatCthulhu Offline
Member

Posts: 213
Threads: 10
Joined: Oct 2010
Reputation: 32
#1
AngelScript OO Capabilities - Inheritance

I see some of you guys have been treading the object-oriented (OO) lands, which is good, so I was wondering if someone could help me with something.

AngelScript OO capabilities are decent, but there are certain odd limitations... At least with the version HPL2 is using. The language designer made some strange choices; while most OO languages provide public, protected and private levels of class member access, AngelScript opts to provide only public and private - but that's not the problem per se.

The following refers to private members only.
If I derive a class (say Derived) from another class (let's call it Base), then:
  • I can access and use the Base private variables from Derived - which means their access modifier is actually equivalent to protected - not a problem.
  • I can override private member functions (as if they were only protected), and get the derived behavior through a Base@ pointer/handle, but I can't call private Base functions from Derived, not even the one that is being overridden, not even from the overriding method. Now that is a strange language design decision to make, and that is the problem.
Anyway, I figured, since Derived can freely access member variables, maybe I could use funcdefs to work around this - the idea was to define a funcdef type, declare a private function pointer in Base, initialize it to point to the private Base member method, and then use it from Derived to make the call...
However, it appears that you can't assign a member method to a function pointer, private or public.

I tried:
@funcPtr = @MemberMethod;
@funcPtr = @Base::MemberMethod;
@funcPtr = @(Base::MemberMethod);


Hell I even tried declaring it like this, hoping for something like C++ member function pointer declaration, knowing it's a long shot:
funcdef void Base::FuncdefType();

None of this works. Dodgy
So, was anyone able to successfully create a funcdef that points to a member function? And if so, could you share how?

Also, anyone tried using namespaces in AngelScript? Are they just namespaces, or are akin to Java packages? It just occurred to me, maybe they can be used to accomplish this, if they support namespace-level private members...

P.S. Another question: IIRC, quite some time ago, Thomas posted something on the blog about using MapView to reload the script along with the map and check the scripts validity that way, by simply pressing the reload button, thus avoiding the (I must say) vicious cycle of (make a stupid syntax error)->(boot up the game)->(load level)->(game crashes)->(read message box)->(do it again)...
Is there a setting in the mapview.cfg to enable this, or something like that? As far as I can tell, map view does not load scripts at all?
Huh

Thanks anyway.
(This post was last modified: 08-16-2012, 04:32 PM by TheGreatCthulhu.)
08-16-2012, 04:29 PM
Find
Your Computer Offline
SCAN ME!

Posts: 3,456
Threads: 32
Joined: Jul 2011
Reputation: 235
#2
RE: AngelScript OO Capabilities - Inheritance

Namespaces are not available in the version of AngelScript that Amnesia uses. I wouldn't expect funcdef to work with methods, mostly given the name of the keyword and that methods require an instance of the class to call anyway. I haven't tried to subclass any of the classes i've made, so i'm not sure of how AngelScript handles inheritance. I can provide a bit more insight on the private keyword, though. Private seems to enforce a void return type (at least for me), so using private on a method that returns a value won't work.

HPL3 is bound to use a newer version of AngelScript and inheritance should more practical and less buggy, since HPL3 seems to rely heavily on interfaces and inheritance.

P.S. It wasn't the MapView program, it was the game itself. If you load the map without any scripting errors, then modify the script and try to reload the map, you can receive errors, if any, without the game exiting.

Tutorials: From Noob to Pro
(This post was last modified: 08-16-2012, 05:14 PM by Your Computer.)
08-16-2012, 05:14 PM
Website Find
TheGreatCthulhu Offline
Member

Posts: 213
Threads: 10
Joined: Oct 2010
Reputation: 32
#3
RE: AngelScript OO Capabilities - Inheritance

(08-16-2012, 05:14 PM)Your Computer Wrote: Namespaces are not available in the version of AngelScript that Amnesia uses. I wouldn't expect funcdef to work with methods, mostly given the name of the keyword and that methods require an instance of the class to call anyway. I haven't tried to subclass any of the classes i've made, so i'm not sure of how AngelScript handles inheritance.
Oh, right - those are instance methods! That made me try and do this (and a few other variants):
@func = @(this.MethodName);
Unfortunately, AngelScript doesn't recognize it as the name of a method - it treats it as an undeclared variable instead. Well then, I guess it's probably better to redesign the class, than to make up hackish, error-prone solutions with little (if any) value.
As for inheritance: except for certain peculiarities, it works pretty well - the benefit in HPL2 context mostly comes if you want to abstract away algorithm details, or when you use it in unison with composition to provide dynamic effects (by dynamically changing class behavior), etc.

(08-16-2012, 05:14 PM)Your Computer Wrote: I can provide a bit more insight on the private keyword, though. Private seems to enforce a void return type (at least for me), so using private on a method that returns a value won't work.
Yeah I noticed that, too. Oh well... Undecided The way I dealt with it, if I really needed to return a value, was by using an out parameter. Something along these lines:
private void SomeMethod(string& input, int &out output) { /* ... */ }

(08-16-2012, 05:14 PM)Your Computer Wrote: P.S. It wasn't the MapView program, it was the game itself. If you load the map without any scripting errors, then modify the script and try to reload the map, you can receive errors, if any, without the game exiting.
Oh, thanks a bunch for that! I should have read the "Setting up Development Environment" wiki more carefully, I just noticed it is explained there.
(This post was last modified: 08-16-2012, 07:04 PM by TheGreatCthulhu.)
08-16-2012, 07:04 PM
Find
Your Computer Offline
SCAN ME!

Posts: 3,456
Threads: 32
Joined: Jul 2011
Reputation: 235
#4
RE: AngelScript OO Capabilities - Inheritance

(08-16-2012, 07:04 PM)TheGreatCthulhu Wrote: Yeah I noticed that, too. Oh well... Undecided The way I dealt with it, if I really needed to return a value, was by using an out parameter. Something along these lines:

private void SomeMethod(string& input, int &out output) { /* ... */ }



That's what i did for the StringList class i posted.

Tutorials: From Noob to Pro
08-16-2012, 07:12 PM
Website Find
TheGreatCthulhu Offline
Member

Posts: 213
Threads: 10
Joined: Oct 2010
Reputation: 32
#5
RE: AngelScript OO Capabilities - Inheritance

Nice Big Grin.
One more question: after reading AngelScript documentation here , I was under the impression that HPL2 didn't provide support for arrays, since AS docs say arrays aren't supported by default, and that that the syntax is:
array<int> a, b, c;

But then, just now I noticed you used string[] internally for your StringList, and tested the C++-like (or rather C#/Java-like) syntax with several array types to see if it compiles (or "interprets", or whatever) - and it does. So, arrays work normally? No ceavats one needs to be aware of there?
Tnx.
(This post was last modified: 08-16-2012, 07:41 PM by TheGreatCthulhu.)
08-16-2012, 07:39 PM
Find
Your Computer Offline
SCAN ME!

Posts: 3,456
Threads: 32
Joined: Jul 2011
Reputation: 235
#6
RE: AngelScript OO Capabilities - Inheritance

(08-16-2012, 07:39 PM)TheGreatCthulhu Wrote: Nice Big Grin.
One more question: after reading AngelScript documentation here , I was under the impression that HPL2 didn't provide support for arrays, since AS docs say arrays aren't supported by default, and that that the syntax is:
array a, b, c;

But then, just now I noticed you used string[] internally for your StringList, and tested the C++-like (or rather C#/Java-like) syntax with several array types to see if it compiles (or "interprets", or whatever) - and it does. So, arrays work normally? No ceavats one needs to be aware of there?
Tnx.

The AngelScript documentation has been updated to match the latest version of AngelScript, which changes the syntax of arrays. The old way of doing it was appending [] to the end of the data type name. Note that not all array methods are implemented for Amnesia. I only know of length() and resize() that works.

Tutorials: From Noob to Pro
(This post was last modified: 08-16-2012, 08:30 PM by Your Computer.)
08-16-2012, 08:05 PM
Website Find
TheGreatCthulhu Offline
Member

Posts: 213
Threads: 10
Joined: Oct 2010
Reputation: 32
#7
RE: AngelScript OO Capabilities - Inheritance

I found a way to do it. Essentially, an object composition based approach. In a way, it's a reduced Bridge pattern.
  • You create two classes: Base and BaseImpl - the implementation class. BaseImpl should only define the implementations of the methods that are to be called from the derived class.
  • You than make a BaseImpl object be a member variable (a.k.a. member field) of Base, and forward all calls to the private methods to their corresponding implementations, via the BaseImpl instance.
  • Finally, since Derived can access private member variables of Base, you simply call the appropriate methods from the subclass.
Essentially:
+---------+                   +----------+
|  Base   |------------------>| BaseImpl |
+---------+                   +----------+
  /|\
   |
   |
<<derives from>>
   |
+---------+
| Derived |
+---------+

Or in code:
PHP Code: (Select All)
class Base
{
    private 
BaseImplimpl;

    
Base()
    {
        @
impl BaseImpl();
    }

    
void DoSomething()
    {
        
// blah, blah...
    
        
OnDoSomething();
    
        
// blah...
    
}
    
    private 
void OnDoSomething()    // the method to be overridden
    
{
        
impl.OnDoSomething();
    }
}

class 
BaseImpl
{
    
void OnDoSomething()
    {
        
/* the implementation */
    
}
}

class 
Derived Base
{
    private 
void OnDoSomething()    // the override
    
{
        
/* <the new implementation> 
         *     blah, blah, blah...
         * </the new implementation> */

        
impl.OnDoSomething();   // calls the base class implementation
    
}

(This post was last modified: 08-17-2012, 12:37 AM by TheGreatCthulhu.)
08-17-2012, 12:31 AM
Find




Users browsing this thread: 4 Guest(s)