- Joined
- May 9, 2014
- Messages
- 1,820
Intro
Encapsulation
Credits
Introduction to Structs
(Part I)
(By MyPad)
Hello reader. By having clicked this link here, I assume that you want to learn structs, right? Yes, you do, and what a wordy tutorial this would be.
What we'll need to have is (either):
1. JNGP or
2. Sharpcraft WEX (for versions 1.24. - 1.29.2)
3. Vanilla World Editor (For 1.30+ above)
What this tutorial will cover:
Part I - Intro
- What is a Struct?
- Declaration of (Independent) Structs
- Members
- Methods
Part II - Encapsulation
- History
- Libraries
- Scopes
I. What is a Struct?
In other programming languages, a struct is called a class.
II. Declaration of (Independent) Structs
JASS:
struct someType
integer count
endstruct
What did we declare here? We declared a struct in vJASS. (JASS does not support this, and vJASS parses a struct into JASS) (You'll know why later on)
Note that to declare a struct (in vJASS), you will have to type it like this:
JASS:
struct <name_of_struct>
endstruct
... and you're good to go.
III. Structs (Members)
Notice that the example before had
integer count
inside the struct. Didn't notice?Well, that was a member of the struct.
The integer count is a member of the struct someType or a data field in the struct. There are two kinds of members: static and normal
Normal members are those that are present per instance.
Static members are those that are reserved to the whole struct.
What's their difference? Let's take a look:
Normal members
JASS:
struct someType
integer count
endstruct
...
local someType that = 3
set that.count = 5
JASS:
struct someType
static integer count
endstruct
...
set someType.count = 5
As you can see, instances or pointers of a struct can use members but they can't use static members because they're not the struct itself (E.g., they're only associated with the struct), while the struct-type (Let's call this struct-type) can use static members but not normal members. Hence, the syntax for using members and static members is:
JASS:
set <struct_instance>.<member> = <some_value>
set <struct_type>.<static_member> = <some_value>
You can also do this:
JASS:
set <struct_type>(<instance>).<member> = <some_value>
IV. Structs (Methods)
Methods are the functions associated with the struct. They also come with two types: static and normal.The static method follows the logic of a static member while a normal method follows the logic of a member.
Syntax:
JASS:
struct SomeType
method foop takes nothing returns nothing
call BJDebugMsg("The enemy of Foop(" + I2S(this) + ") is Poof(" + I2S(this) + ").")
endmethod
static method foo takes nothing returns nothing
call DoNothing()
call BJDebugMsg("You've been bamboozled")
endmethod
endstruct
...
local SomeType fool = 5
call SomeType.foo()
call fool.foop()
V. Conclusion
I hope that you have learned something here. If not, just leave a reply here asking why you do not understand or you can send a query via PM. Who knows, I might add you to the credits list.
Encapsulation
(Part II)
It looks like we meet again, fellow reader. Welcome to Part II of the tutorial. By clicking on this tab, I assume that you've already learned everything about Part I.
So, let us begin!
History
vJASS was and still is the go-to scripting language for the majority of the community members. In essence, vJASS is how some compiler engineers or enthusiastic coders would have programmed the language, and is like the first-born child of JASS2 (figuratively speaking).
Under all fanciful syntax and such, vJASS is an abstraction for JASS2, which then gets compiled to JASS2 (which shall be referred hereafter as JASS) through JassHelper. How JassHelper compiles vJASS to JASS is another topic altogether and shall be linked here:
Coverage
What this part will discuss:
- Libraries
- Scopes
- Scopes within Libraries
- Scopes within Scopes
Pre-Discussion Questions
Q: Wait, all this part is talking about isn't even about structs! Where's our structs?
A: It will be covered, although structs are going to be talked about a little bit here.
I. Libraries
Libraries are containers of packets of code. They're like juice cartons, where the juice is the code and the carton is the enclosure, which is representative of a library.
Libraries are very useful in keeping the code organized, or at least, the thought-process or the logic of the code. Libraries are what enforces modularity in writing code, but we'll deal with it later. To declare a library:
JASS:
library MyLibrary
public function foo takes nothing returns nothing
endfunction
endlibrary
One must declare the keyword "library" and assign a unique name to the library. Due to vJASS being based on JASS, one must also declare "endlibrary" at the end of the script. This becomes second-nature very quickly.
If you can notice, a function foo was declared within the library. Now, what's with the prefix "public"?
Let's see the compiled result:
JASS:
// MyLibrary starts
function MyLibrary_foo takes nothing returns nothing
endfunction
// MyLibrary ends
Looks like foo got prefixed with the name of the library. Neat'o, isn't it?
From the example, we can see that the function that's prefixed with "public" inherits the name of the library as a prefix. Why is it so?
JASS:
library MyLibrary1
public function foo takes nothing returns nothing
endfunction
endlibrary
library MyLibrary2
public function foo takes nothing returns nothing
endfunction
endlibrary
// ...
call foo() // error
Now, let's look at the compiled result: (Order may vary, explanation later)
JASS:
// MyLibrary1 begins
function MyLibrary1_foo takes nothing returns nothing
endfunction
// MyLibrary1 ends
// MyLibrary2 begins
function MyLibrary2_foo takes nothing returns nothing
endfunction
// MyLibrary2 ends
// ...
call foo() // error
As you can see, libraries look like they are giving the packets of code within them their own space. This gives them a sense of organization. Remember that the functions were "public"? Well, it does look like the functions are given unique names, which means that you can keep using the same name of a function, as long as you add some encapsulation prefixes.
The most commonly used prefixes for encapsulation are "public, private". These prefixes for encapsulation, these keywords, allow functions with the same name in compile-time to be differentiated from each other, as long as the library names are different.
A simple explanation for "public" and "private" keywords are as follows; they behave just as their meaning implies.
Now, the code within libraries is moved to the top, which allow functions below to call the library code. However, the compiler will mix the order of compilation of libraries, which could make for some unintended errors if trying to call functions from other libraries. How can we resolve this?
JASS:
library MyLibrary1
endlibrary
library MyLibrary2 uses MyLibrary1 // keywords needs, requires are also usable here.
endlibrary
So, what's with the keyword "uses"? The library doesn't seem to be doing anything, right?
The keyword "uses" is instructing the compiler to put the desired library before the library itself.
In another sense, it tells the compiler that that used library should be placed above it, since it may use its' features or functions.
To make it more clear, an example of it is as follows:
JASS:
// MyLibrary1 begins
// MyLibrary1 ends
// MyLibrary2 begins
// MyLibrary2 ends
So far, nothing has changed from our previous example except we took out some unnecessary functions. However, the main difference between the former and the latter is that the order is deterministic, which means in here that MyLibrary2 will always be below MyLibrary1 no matter what. This further organizes the script into the way that would seem most logical.
II. Scopes
Scopes are functionally similar to libraries, only that they are moved way below the library section. It would only make sense when it is understood in a sense that scopes are just the local functions relative to the map, while the libraries are global, being shared across maps. In another sense, they're only relevant to the map at hand.
A good example of such scopes are spells. Spells do not need to be placed in the library section, since nothing from below is presumed to call them. They are, in a sense, reserved to themselves, and nothing should change that by calling them.
While this is all fine and dandy, an example should best explain what happens.
Input:
Output:
Don't let the scrambling of the order of libraries fool you. Look at MyScope. It is at the bottom of the libraries.
Let's try compiling it again.
Output:
Huh, looks like we encounter this case again. MyScope can't seem to go up.
It is rather bittersweet to know that scopes can never be above libraries, no matter how many times we compile them.
There is also another feature of scopes, the ability to enclose individual scopes within it. Basically, you can declare a scope inside a scope, and the same inside a library. But, what would happen if we place a library within a scope?
Huh? It would not compile, no matter how many times you will save it. So, declaring a scope within a scope or a library is A-Okay but placing a library inside a scope is a no-no? Yes, it is, because of a simple reason, a scope can never be above libraries, and trying to move that library in the scope up would cause a violation of that rule.
A good example of such scopes are spells. Spells do not need to be placed in the library section, since nothing from below is presumed to call them. They are, in a sense, reserved to themselves, and nothing should change that by calling them.
While this is all fine and dandy, an example should best explain what happens.
Input:
JASS:
library MyLibrary1
endlibrary
library MyLibrary2
endlibrary
scope MyScope
endscope
Output:
JASS:
// MyLibrary2 begins
// MyLibrary2 ends
// MyLibrary1 begins
// MyLibrary1 ends
// MyScope begins
// MyScope ends
Don't let the scrambling of the order of libraries fool you. Look at MyScope. It is at the bottom of the libraries.
Let's try compiling it again.
Output:
JASS:
// MyLibrary1 begins
// MyLibrary1 ends
// MyLibrary2 begins
// MyLibrary2 ends
// MyScope begins
// MyScope ends
Huh, looks like we encounter this case again. MyScope can't seem to go up.
It is rather bittersweet to know that scopes can never be above libraries, no matter how many times we compile them.
There is also another feature of scopes, the ability to enclose individual scopes within it. Basically, you can declare a scope inside a scope, and the same inside a library. But, what would happen if we place a library within a scope?
JASS:
scope MyScope
library MyScopeLib
endlibrary
endscope
// Won't compile ...
Huh? It would not compile, no matter how many times you will save it. So, declaring a scope within a scope or a library is A-Okay but placing a library inside a scope is a no-no? Yes, it is, because of a simple reason, a scope can never be above libraries, and trying to move that library in the scope up would cause a violation of that rule.
III. Recap
To recap, libraries are containers that give code their own space (or something like it). They encapsulate the functions so as to add protection from unintentional reading or access. When using the keywords "uses, requires or needs", the library that requires the other library will be moved below it.
Scopes are similar to libraries in that they give code their own space as well. In basic form, they are libraries that require all libraries before it, but not needing to declare them as requirements.
Now, without compiling the code, would the following code compile without a trigger-evaluation (e.g. not compiling in the vanilla trigger editor)?
JASS:
library MyLibrary2 uses MyLibrary1
public struct Struct
static method doElse takes nothing returns nothing
endmethod
endstruct
endlibrary
library MyLibrary1
function doSomething takes nothing returns nothing
call MyLibrary2_Struct.doElse()
endfunction
endlibrary
Or, say we have this. Would this compile?
JASS:
library MyLibrary1
private function foo takes nothing returns nothing
call BJDebugMsg("boop")
endfunction
endlibrary
library MyLibrary2 uses MyLibrary1
private function bar takes nothing returns nothing
call MyLibrary1_foo()
endfunction
endlibrary
Cuore for asking questions and clarifications about the struct tutorial...
IcemanBo for providing links to other tutorials...
Thanks for taking your time to read this tutorial!
Last edited: