Ffl classes

davewx7 edited this page Nov 17, 2012 · 1 revision
Clone this wiki locally

Why Classes?

FFL supports maps -- simple dictionaries of data. It also supports objects -- types which resemble maps from the point of view of FFL, but which can be coded in C++ to have all sorts of special behavior. Using C++ we can define an object that executes custom functionality when a key is set or read from the object.

Classes are a way to allow FFL to do this too -- to define special kinds of objects that look and behave very much like maps, but which have special behavior when keys are queried or set. Classes aren't really a "native" FFL feature, in that the core FFL language knows nothing about them. Rather, they are simply FFL objects that have been written in C++ to delegate behavior back to FFL.

Defining a class

You can define a class by putting its definition in data/classes/xxx.cfg where 'xxx' is the name of your class. A class may itself have sub-classes, defined in its classes attribute.

A class is composed of a public interface, which is defined as a set of properties. A class stores its data in an FFL map, called simply 'private'. The properties of a class can freely access private, but it cannot be accessed in any other way. Thus, classes enforce data hiding -- anything wanting to get to the data an instance of the class holds must go through the class's properties.

Suppose we wanted to implement a Monopoly-like game, and use a class to represent a property. Here is what we might have in classes/monopoly_property.cfg:

{
properties: {
  cost: { variable: true, default: 100},  //the variable: true makes this equivalent to having
                                          //set: "set(private.cost, value)", get: "private.cost"
                                          // -- i.e. it makes it automatically back-end the property
                                          //onto a variable stored in private.

  name: { variable: true },
  board_segment: { variable: true, default: 0 },

  num_houses: { get: "private.num_houses",
                set: "if(value >= 0 and value <= 4, set(private.num_houses, value))"  },

  house_price: "(board_segment+1)*50",  //equivalent to { get: "(board_segment+1)*50" }
  },

private: {} // Optionally we can specify what private should be initialized to upon construction
            // of a class instance. Initializing to an empty map is the default behavior.
}

You could construct an instance of this using FFL:

construct('monopoly_property', { name: 'Park Lane', cost: 350, board_segment: 3 })

This constructs an instance of the class. The map argument represents properties to set immediately upon construction.