OOP support.

This commit is contained in:
Stephen Chung
2020-06-26 10:39:18 +08:00
parent 259b6d0fcf
commit 175c3ccaec
27 changed files with 498 additions and 234 deletions

View File

@@ -1,6 +1,8 @@
Function Pointers
=================
{{#include ../links.md}}
It is possible to store a _function pointer_ in a variable just like a normal value.
In fact, internally a function pointer simply stores the _name_ of the function as a string.

View File

@@ -53,29 +53,6 @@ fn foo() { x } // <- syntax error: variable 'x' doesn't exist
```
Arguments Passed by Value
------------------------
Functions defined in script always take [`Dynamic`] parameters (i.e. the parameter can be of any type).
Therefore, functions with the same name and same _number_ of parameters are equivalent.
It is important to remember that all arguments are passed by _value_, so all Rhai script-defined functions
are _pure_ (i.e. they never modify their arguments).
Any update to an argument will **not** be reflected back to the caller.
This can introduce subtle bugs, if not careful, especially when using the _method-call_ style.
```rust
fn change(s) { // 's' is passed by value
s = 42; // only a COPY of 's' is changed
}
let x = 500;
x.change(); // de-sugars to 'change(x)'
x == 500; // 'x' is NOT changed!
```
Global Definitions Only
----------------------
@@ -106,3 +83,47 @@ A function does not need to be defined prior to being used in a script;
a statement in the script can freely call a function defined afterwards.
This is similar to Rust and many other modern languages, such as JavaScript's `function` keyword.
Arguments Passed by Value
------------------------
Functions defined in script always take [`Dynamic`] parameters (i.e. the parameter can be of any type).
Therefore, functions with the same name and same _number_ of parameters are equivalent.
It is important to remember that all arguments are passed by _value_, so all Rhai script-defined functions
are _pure_ (i.e. they never modify their arguments).
Any update to an argument will **not** be reflected back to the caller.
```rust
fn change(s) { // 's' is passed by value
s = 42; // only a COPY of 's' is changed
}
let x = 500;
change(x);
x == 500; // 'x' is NOT changed!
```
`this` - Simulating an Object Method
-----------------------------------
Functions can also be called in method-call style. When this is the case, the keyword '`this`'
binds to the object in the method call and can be changed.
```rust
fn change() { // not that the object does not need a parameter
this = 42; // 'this' binds to the object in method-call
}
let x = 500;
x.change(); // call 'change' in method-call style, 'this' binds to 'x'
x == 42; // 'x' is changed!
change(); // <- error: `this` is unbounded
```

View File

@@ -57,13 +57,13 @@ if the first one already proves the condition wrong.
Single boolean operators `&` and `|` always evaluate both operands.
```rust
this() || that(); // that() is not evaluated if this() is true
a() || b(); // b() is not evaluated if a() is true
this() && that(); // that() is not evaluated if this() is false
a() && b(); // b() is not evaluated if a() is false
this() | that(); // both this() and that() are evaluated
a() | b(); // both a() and b() are evaluated
this() & that(); // both this() and that() are evaluated
a() & b(); // both a() and b() are evaluated
```
Compound Assignment Operators

View File

@@ -0,0 +1,23 @@
Special Support for OOP via Object Maps
======================================
{{#include ../links.md}}
[Object maps] can be used to simulate object-oriented programming ([OOP]) by storing data
as properties and methods as properties holding [function pointers].
If an [object map]'s property holding a [function pointer] is called in method-call style,
it calls the function referenced by the [function pointer].
```rust
fn do_action(x) { print(this + x); } // 'this' binds to the object when called
let obj = #{
data: 40,
action: Fn("do_action") // 'action' holds a function pointer to 'do_action'
};
obj.action(2); // prints 42
obj.action.call(2); // <- the above de-sugars to this
```

44
doc/src/language/oop.md Normal file
View File

@@ -0,0 +1,44 @@
Object-Oriented Programming (OOP)
================================
{{#include ../links.md}}
Rhai does not have _objects_ per se, but it is possible to _simulate_ object-oriented programming.
Use [Object Maps] to Simulate OOP
--------------------------------
Rhai's [object maps] has [special support for OOP]({{rootUrl}}/language/object-maps-oop.md).
| Rhai concept | Maps to OOP |
| ----------------------------------------------------- | :---------: |
| [Object maps] | objects |
| [Object map] properties holding values | properties |
| [Object map] properties that hold [function pointers] | methods |
Examples
--------
```rust
// Define the object
let obj = #{
data: 0,
increment: Fn("add"), // when called, 'this' binds to 'obj'
update: Fn("update"), // when called, 'this' binds to 'obj'
action: Fn("action") // when called, 'this' binds to 'obj'
};
// Define functions
fn add(x) { this.data += x; } // update using 'this'
fn update(x) { this.data = x; } // update using 'this'
fn action() { print(this.data); } // access properties of 'this'
// Use the object
obj.increment(1);
obj.action(); // prints 1
obj.update(42);
obj.action(); // prints 42
```