Reference Types
Interfaces in the MAXON API can be "virtual" or "non-virtual" interfaces. Such interfaces can be registered using different reference types. These reference types define how the created reference classes are build and how they behave.
These reference types are applicable to virtual and non-virtual interfaces:
const
functions are handed over to the reference class.
An interface using
MAXON_REFERENCE_CONST
only adds
const
functions to the created reference class. To create instances of such a read-only object a helper interface might be used that is able to create different objects (see also
Factories
).
The declaration of the
const
interface and the helper interface could look like this:
// --------------------------------------------------------------------- // A custom unique ID class. // --------------------------------------------------------------------- class CustomUniqueIdInterface : MAXON_INTERFACE_BASES (maxon::ObjectInterface) { MAXON_INTERFACE (CustomUniqueIdInterface, MAXON_REFERENCE_CONST , "net.maxonexample.interfaces.uniqueid" );
// forward declaration of the reference class // const classes do not use the suffix "Ref" class CustomUniqueId;
// --------------------------------------------------------------------- // Non-virtual interface as a CustomUniqueId generator. // --------------------------------------------------------------------- class CustomUniqueIdGenerator { MAXON_INTERFACE_NONVIRTUAL (CustomUniqueIdGenerator, MAXON_REFERENCE_NONE , "net.maxonexample.interfaces.uniqueidgenerator" );
The implementation of the
const
class can look like this. Notice the
Init()
function that takes an argument:
// implementation of CustomUniqueIdInterface class UniqueIdImp : public maxon::Component <UniqueIdImp, CustomUniqueIdInterface> { MAXON_COMPONENT (); public : maxon::ResultOk<void> Init( maxon::UInt id ) { _id = id; return maxon::OK ; } MAXON_METHOD maxon::UInt GetId() const { return _id; } private : maxon::UInt _id; };
The implementation of the helper interface creates a new object by creating a new instance of the component. Calling
CreateInit()
will invoke the above
Init()
函数。
// create new UniqueId return UniqueIdImp::CreateInit(g_uniqueIDs); }
Now one can use the helper interface to create a new instance of the read-only
const
interface.
// create ID const CustomUniqueId id = CustomUniqueIdGenerator::GetUniqueID() iferr_return ;
// use ID const maxon :: UInt value = id .GetId(); DiagnosticOutput ("UID: @", value);
If an object of a copy-on-write class is copied, it will not copy its content. It will only store a reference to the original object. Only if the copy or original object are changed, data is copied.
A simple copy-on-write interface can look like this:
// This example shows a simple interface of the reference type MAXON_REFERENCE_COPY_ON_WRITE.// --------------------------------------------------------------------- // Class to store an array of maxon::Float values. // --------------------------------------------------------------------- class FloatArrayInterface : MAXON_INTERFACE_BASES (maxon::ObjectInterface) { MAXON_INTERFACE (FloatArrayInterface, MAXON_REFERENCE_COPY_ON_WRITE , "net.maxonexample.interfaces.floatarray" ); public : // --------------------------------------------------------------------- // Adds the given value to the array. // --------------------------------------------------------------------- MAXON_METHOD maxon::Result<void> AddValue( maxon::Float value); };
The implementation is straightforward:
// This example shows an implementation of a copy-on-write interface.// implementation of FloatArrayInterface class FloatArrayImpl : public maxon::Component <FloatArrayImpl, FloatArrayInterface> { MAXON_COMPONENT (); public : // implementation of an interface function MAXON_METHOD maxon::Result<void> AddValue( maxon::Float value) { return _data.Append(value); }
// implementation of maxon::ComponentRoot::CopyFrom() maxon::Result<void> CopyFrom( const FloatArrayImpl& arr) { return _data.CopyFrom(arr._data); }
// implementation of maxon::ObjectInterface::ToString() MAXON_METHOD maxon::String ToString ( const maxon::FormatStatement * formatStatement) const { maxon::String result { "Values: " }; for ( const maxon::Float v : _data) result += maxon::String::FloatToString(v) + ", " _s; return result; } private : maxon::BaseArray<maxon::Float> _data; };
The reference class of a copy-on-write interface does not use the usual "Ref" suffix. It can be used as usual:
// This example creates and uses copy-on-write objects.// create original FloatArray original = componentClass.Create() iferr_return ; // use original original.AddValue(1.0) iferr_return ; original.AddValue(2.0) iferr_return ;
// create copy FloatArray copy = componentClass.Create() iferr_return ;
// data is assigned but not yet copied copy = original;
// original and copy have access to the same data DiagnosticOutput ( "Original: @" , original); DiagnosticOutput ( "Copy: @" , copy);
// add further data; internal data will now be copied copy.AddValue(3.0) iferr_return ;
// original and copy now access different data DiagnosticOutput ( "Original: @" , original); DiagnosticOutput ( "Copy: @" , copy);
These reference types are only applicable to non-virtual interfaces:
const
C++ pointer without reference counting.
Non-virtual interfaces can use the reference type MAXON_REFERENCE_NONE . This will create a static reference class.
The non-virtual interface is declared like this:
// This example shows a simple non-virtual interface of the reference type MAXON_REFERENCE_NONE.// --------------------------------------------------------------------- // Class to roll a dice. // --------------------------------------------------------------------- class DiceInterface { MAXON_INTERFACE_NONVIRTUAL (DiceInterface, MAXON_REFERENCE_NONE , "net.maxonexample.interfaces.dice" ); public : // --------------------------------------------------------------------- // Rolls the dice and returns a random number. // --------------------------------------------------------------------- static MAXON_METHOD maxon::UInt RollDice(); };
The implementation can look like this:
// This example shows the implementation of a simple interface.// implementation of DiceInterface class DiceInterfaceImpl : protected DiceInterface { MAXON_IMPLEMENTATION (DiceInterfaceImpl) public : static maxon::UInt RollDice(); };
// implementation of DiceInterface::RollDice() maxon::UInt DiceInterfaceImpl::RollDice() { // chosen by fair dice roll. // guaranteed to be random. return 4; } MAXON_IMPLEMENTATION_REGISTER (DiceInterfaceImpl);
The static reference class is used this way:
// This example uses the static member function of the interface. const maxon::UInt randomNumber = DiceInterface::RollDice(); DiagnosticOutput ( "Number: @" , randomNumber);