Jump to content

Programming Reference:Class Hierarchies: Difference between revisions

From BCI2000 Wiki
Mellinger (talk | contribs)
No edit summary
 
Mellinger (talk | contribs)
No edit summary
Line 1: Line 1:
BCI2000 consists of a large number of classes, which interact in complicated ways, and are difficult to oversee. Most of these classes are of little importance to the overall picture of BCI2000. In fact, knowledge of a small number of BCI2000 classes, and their inheritance relationships, is sufficient to understand how BCI2000 works, and how to write your own BCI2000 filters and modules.
BCI2000 consists of a large number of classes, which interact in complicated ways, and are difficult to oversee. Most of these classes are of little importance to the overall picture of BCI2000. In fact, knowledge of a small number of BCI2000 classes, and their inheritance relationships, is sufficient to understand how BCI2000 works, and how to write your own BCI2000 filters and modules.


This page gives an overview over the class hierarchies which matter to you when doing programming work in BCI2000. It does not describe individual self-contained classes such as the [Programming Reference:SignalProperties Class|''SignalProperties''] or [Programming Reference:GenericSignal Class|''GenericSignal'']; rather, it explains classes that are part of hierarchies, each playing a certain role in its hierarchy.
This page gives an overview over the class hierarchies which matter to you when doing programming work in BCI2000. It does not describe individual self-contained classes such as the [[Programming Reference:SignalProperties Class|''SignalProperties'']] or [[Programming Reference:GenericSignal Class|''GenericSignal'']]; rather, it explains classes that are part of hierarchies, each playing a certain role in its hierarchy.


==Types of Classes==
==Types of Classes==
Line 11: Line 11:
Interface classes typically declare a number of so-called virtual functions. In the interface class, these virtual functions do nothing specific; in most cases, they are not even defined, such that a derived class is forced to implement its own version of that function. An interface class' virtual functions provide an interface to their derived classes. In addition to virtual functions, an interface class also has plain member functions; these provide an interface to classes that use objects of the interface class, rather than inheriting from it.
Interface classes typically declare a number of so-called virtual functions. In the interface class, these virtual functions do nothing specific; in most cases, they are not even defined, such that a derived class is forced to implement its own version of that function. An interface class' virtual functions provide an interface to their derived classes. In addition to virtual functions, an interface class also has plain member functions; these provide an interface to classes that use objects of the interface class, rather than inheriting from it.


In BCI2000, there are a large number of interface classes that represent programming interfaces for filters, data acquisition interfaces, file writers, application modules, and graphic objects. The most important interface class is the [Programming Reference:GenericFilter Class|''GenericFilter''] class, which defines the programming interface for all BCI2000 filter components that are part of the [Programming Reference:Filter Chain|filter chain].
In BCI2000, there are a large number of interface classes that represent programming interfaces for filters, data acquisition interfaces, file writers, application modules, and graphic objects. The most important interface class is the [[Programming Reference:GenericFilter Class|''GenericFilter'']] class, which defines the programming interface for all BCI2000 filter components that are part of the [[Programming Reference:Filter Chain|filter chain]].


Most often, interfaces are built around the notion of an "event". When an event happens, it requires an action. Actions are defined by client classes that implement an interface. Each virtual function in the interface corresponds to an event, and derived classes implement those functions, thus providing event "handlers". As an example, the [Programming Reference:GraphObject Class|''GraphObject''] interface class declares a virtual function called ''OnPaint()''. Individual graphic objects inherit from the ''GraphObject'' class, and implement the associated interface by providing their own ''OnPaint()'' function. Whenever a window needs redrawing, graphic objects are asked to handle the ''Paint'' event, i.e. for all graphic objects tied to the respective window, the ''OnPaint()'' event handler is called. In its ''OnPaint()'' function, a ''GraphObject'' descendant class that represents a circle will provide code that draws a circle, while a ''GraphObject'' descendant representing a text field will implement an ''OnPaint()'' event handler that draws text.
Most often, interfaces are built around the notion of an "event". When an event happens, it requires an action. Actions are defined by client classes that implement an interface. Each virtual function in the interface corresponds to an event, and derived classes implement those functions, thus providing event "handlers". As an example, the [[Programming Reference:GraphObject Class|''GraphObject'']] interface class declares a virtual function called ''OnPaint()''. Individual graphic objects inherit from the ''GraphObject'' class, and implement the associated interface by providing their own ''OnPaint()'' function. Whenever a window needs redrawing, graphic objects are asked to handle the ''Paint'' event, i.e. for all graphic objects tied to the respective window, the ''OnPaint()'' event handler is called. In its ''OnPaint()'' function, a ''GraphObject'' descendant class that represents a circle will provide code that draws a circle, while a ''GraphObject'' descendant representing a text field will implement an ''OnPaint()'' event handler that draws text.


Most often, classes directly inherit from a single interface class only, e.g. when you write a BCI2000 filter component, it inherits from the ''GenericFilter'' interface class. However, it is not uncommon that there is a hierarchy of interface classes which all build upon each other, where the line of inheritage represents increasing specialization. As an example, all BCI2000 filters inherit from the ''GenericFilter'' interface class. However, data acquisition filters do not inherit from ''GenericFilter'' directly; rather, they inherit from a class called [Programming Reference:GenericADC Class|''GenericADC''], which in turn inherits from ''GenericFilter'', i.e. it specializes the ''GenericFilter'' interface for data acquisition components. In addition, there exists an interface class called [Programming Reference:BufferedADC Class|''BufferedADC''] which provides buffering, and an interface for data acquisition components that write their acquired data into a ring buffer. A class that inherits the ''BufferedADC'' interface thus implements an interface that has been specialized all the way down from ''GenericADC'' and ''GenericFilter'' to ''BufferedADC''.  
Most often, classes directly inherit from a single interface class only, e.g. when you write a BCI2000 filter component, it inherits from the ''GenericFilter'' interface class. However, it is not uncommon that there is a hierarchy of interface classes which all build upon each other, where the line of inheritage represents increasing specialization. As an example, all BCI2000 filters inherit from the ''GenericFilter'' interface class. However, data acquisition filters do not inherit from ''GenericFilter'' directly; rather, they inherit from a class called [[Programming Reference:GenericADC Class|''GenericADC'']], which in turn inherits from ''GenericFilter'', i.e. it specializes the ''GenericFilter'' interface for data acquisition components. In addition, there exists an interface class called [[Programming Reference:BufferedADC Class|''BufferedADC'']] which provides buffering, and an interface for data acquisition components that write their acquired data into a ring buffer. A class that inherits the ''BufferedADC'' interface thus implements an interface that has been specialized all the way down from ''GenericADC'' and ''GenericFilter'' to ''BufferedADC''.  


===Mix-in Classes===
===Mix-in Classes===
Unlike interface classes, which provide a more-or-less empty framework to be filled in by descendant classes, mix-in classes do actually implement functionality. This functionality is contained in non-virtual functions which may be declared "protected" to make them accessible only to classes that inherit from the mix-in class. An example of such a mix-in class in BCI2000, is the [Programming Reference:Environment Class|''Environment''] class, which provides access to the [Programming Reference:Parameters|Parameters] and [Programming Reference:States|States] that exist in the system. As ''GenericFilter'' inherits from ''Environment'', most BCI2000 components inherit from ''Environment'' without explicitly asking for it. However, any class that wants to access parameters or states may inherit from the ''Environment'' class.
Unlike interface classes, which provide a more-or-less empty framework to be filled in by descendant classes, mix-in classes do actually implement functionality. This functionality is contained in non-virtual functions which may be declared "protected" to make them accessible only to classes that inherit from the mix-in class. An example of such a mix-in class in BCI2000, is the [[Programming Reference:Environment Class|''Environment'']] class, which provides access to the [[Programming Reference:Parameters|Parameters]] and [[Programming Reference:States|States]] that exist in the system. As ''GenericFilter'' inherits from ''Environment'', most BCI2000 components inherit from ''Environment'' without explicitly asking for it. However, any class that wants to access parameters or states may inherit from the ''Environment'' class.


===Client Classes===
===Client Classes===
Client classes are at the bottom of the inheritance hierarchy. They implement inherited interfaces, and use the functionality provided by mix-in classes, to actually get something done. E.g., the [User Reference:LinearClassifier|''LinearClassifier''] class implements the ''GenericFilter'' interface, using the mix-in functionality of the ''Environment'' class, resulting in a BCI2000 component that applies a linear classifier to a stream of data.
Client classes are at the bottom of the inheritance hierarchy. They implement inherited interfaces, and use the functionality provided by mix-in classes, to actually get something done. E.g., the [[User Reference:LinearClassifier|''LinearClassifier'']] class implements the ''GenericFilter'' interface, using the mix-in functionality of the ''Environment'' class, resulting in a BCI2000 component that applies a linear classifier to a stream of data.
The [User Reference:StimulusPresentationTask|''StimulusPresentationTask''] class implements the [Programming Reference:StimulusTask Class|''StimulusTask''] interface, which in turn is a specialization of the ''GenericFilter'' interface, and inherits functionality from the [Programming Reference:ApplicationBase Class|''ApplicationBase''] base class.
The [[User Reference:StimulusPresentationTask|''StimulusPresentationTask'']] class implements the [[Programming Reference:StimulusTask Class|''StimulusTask'']] interface, which in turn is a specialization of the ''GenericFilter'' interface, and inherits functionality from the [[Programming Reference:ApplicationBase Class|''ApplicationBase'']] base class.

Revision as of 16:29, 12 August 2011

BCI2000 consists of a large number of classes, which interact in complicated ways, and are difficult to oversee. Most of these classes are of little importance to the overall picture of BCI2000. In fact, knowledge of a small number of BCI2000 classes, and their inheritance relationships, is sufficient to understand how BCI2000 works, and how to write your own BCI2000 filters and modules.

This page gives an overview over the class hierarchies which matter to you when doing programming work in BCI2000. It does not describe individual self-contained classes such as the SignalProperties or GenericSignal; rather, it explains classes that are part of hierarchies, each playing a certain role in its hierarchy.

Types of Classes

In BCI2000, class hierarchies consist of three types of classes: Interface class, mix-in classes, and client classes.

Interface Classes

Interface classes, which provide an abstract interface for functionality that is then implemented by classes derived from those interface classes. Due to the common interface, the BCI2000 framework can deal with a great number of derived classes, serving their needs without even knowing which derived classes exist and what they do.

Interface classes typically declare a number of so-called virtual functions. In the interface class, these virtual functions do nothing specific; in most cases, they are not even defined, such that a derived class is forced to implement its own version of that function. An interface class' virtual functions provide an interface to their derived classes. In addition to virtual functions, an interface class also has plain member functions; these provide an interface to classes that use objects of the interface class, rather than inheriting from it.

In BCI2000, there are a large number of interface classes that represent programming interfaces for filters, data acquisition interfaces, file writers, application modules, and graphic objects. The most important interface class is the GenericFilter class, which defines the programming interface for all BCI2000 filter components that are part of the filter chain.

Most often, interfaces are built around the notion of an "event". When an event happens, it requires an action. Actions are defined by client classes that implement an interface. Each virtual function in the interface corresponds to an event, and derived classes implement those functions, thus providing event "handlers". As an example, the GraphObject interface class declares a virtual function called OnPaint(). Individual graphic objects inherit from the GraphObject class, and implement the associated interface by providing their own OnPaint() function. Whenever a window needs redrawing, graphic objects are asked to handle the Paint event, i.e. for all graphic objects tied to the respective window, the OnPaint() event handler is called. In its OnPaint() function, a GraphObject descendant class that represents a circle will provide code that draws a circle, while a GraphObject descendant representing a text field will implement an OnPaint() event handler that draws text.

Most often, classes directly inherit from a single interface class only, e.g. when you write a BCI2000 filter component, it inherits from the GenericFilter interface class. However, it is not uncommon that there is a hierarchy of interface classes which all build upon each other, where the line of inheritage represents increasing specialization. As an example, all BCI2000 filters inherit from the GenericFilter interface class. However, data acquisition filters do not inherit from GenericFilter directly; rather, they inherit from a class called GenericADC, which in turn inherits from GenericFilter, i.e. it specializes the GenericFilter interface for data acquisition components. In addition, there exists an interface class called BufferedADC which provides buffering, and an interface for data acquisition components that write their acquired data into a ring buffer. A class that inherits the BufferedADC interface thus implements an interface that has been specialized all the way down from GenericADC and GenericFilter to BufferedADC.

Mix-in Classes

Unlike interface classes, which provide a more-or-less empty framework to be filled in by descendant classes, mix-in classes do actually implement functionality. This functionality is contained in non-virtual functions which may be declared "protected" to make them accessible only to classes that inherit from the mix-in class. An example of such a mix-in class in BCI2000, is the Environment class, which provides access to the Parameters and States that exist in the system. As GenericFilter inherits from Environment, most BCI2000 components inherit from Environment without explicitly asking for it. However, any class that wants to access parameters or states may inherit from the Environment class.

Client Classes

Client classes are at the bottom of the inheritance hierarchy. They implement inherited interfaces, and use the functionality provided by mix-in classes, to actually get something done. E.g., the LinearClassifier class implements the GenericFilter interface, using the mix-in functionality of the Environment class, resulting in a BCI2000 component that applies a linear classifier to a stream of data. The StimulusPresentationTask class implements the StimulusTask interface, which in turn is a specialization of the GenericFilter interface, and inherits functionality from the ApplicationBase base class.