Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
143 lines (92 sloc) 3.89 KB
% Copyright (C) 2003-2019 Olivier Boudeville
%
% This file is part of the Ceylan-WOOPER examples.
%
% It has been placed in the public domain.
%
% Author: Olivier Boudeville [olivier (dot) boudeville (at) esperide (dot) com]
%
-module(class_Mammal).
-define( class_description, "Class modelling any kind of mammal.").
% Determines what are the direct mother classes of this class (if any):
-define( superclasses, [ class_Creature ] ).
-define( class_attributes, [ fur_color ] ).
% Allows to define WOOPER base variables and methods for that class:
-include("wooper.hrl").
% Import common types without module prefix:
-include("ecosystem_types.hrl").
% Constructs a new Mammal.
-spec construct( wooper:state(), age(), gender(), fur_color() ) ->
wooper:state().
construct( State, Age, Gender, FurColor ) ->
CreatureState = class_Creature:construct( State, Age, Gender ),
{ RequestedState, ActualClass } =
executeRequest( CreatureState, getClassname ),
% Even when constructing a cat, we should see the right class (class_Cat)
% and not the current class (class_Mammal):
%
io:format( "Actual class from constructor: ~s.~n", [ ActualClass ] ),
setAttribute( RequestedState, fur_color, FurColor ).
% Overriding default destructor: state should be returned, and destructors
% should be called in leaf-to-root order in inheritance tree.
%
-spec destruct( wooper:state() ) -> wooper:state().
destruct( State ) ->
{ RequestedState, ActualClass } =
executeRequest( State, getClassname ),
% Even when constructing a cat, we should see the right class (class_Cat)
% and not the current class (class_Mammal):
io:format( "Actual class from destructor: ~s.~n", [ ActualClass ] ),
io:format( "Deleting mammal ~w! (overridden destructor)~n", [ self() ] ),
RequestedState.
% Method implementations.
% Sets correctly the age of this Mammal (not like faulty implementation of the
% Creature mother class).
%
% Overridden from Creature, useful to show the use of executeOneway.
%
-spec setAge( wooper:state(), age() ) -> oneway_return().
setAge( State, NewAge ) ->
%trace_utils:debug( "class_Mammal:setAge/2 called." ),
% If needing to test the crash of a oneway:
%A=1,
%B=2,
%A=B,
wooper:return_state( setAttribute( State, age, NewAge ) ).
% All mammals are hot-blooded:
-spec isHotBlooded( wooper:state() ) -> const_request_return( boolean() ).
isHotBlooded( State ) ->
wooper:const_return_result( true ).
% Attribute names could be defined in '-define().' header (.hrl) clauses, to
% ensure consistency.
%
-spec getFurColor( wooper:state() ) -> const_request_return( fur_color() ).
getFurColor( State ) ->
wooper:const_return_result( ?getAttr(fur_color) ).
% Returns a class-specific arbitrary number.
% Overridden from Creature, useful to show the use of executeRequest.
%
-spec getArbitraryNumber( wooper:state() ) -> request_return( number() ).
getArbitraryNumber( State ) ->
{ RequestedState, ActualClass } = executeRequest( State,
getClassname ),
% Even when constructing a cat, we should see the right class (class_Cat)
% and not the current class (class_Mammal):
%
io:format( "Actual class from non-overridden method: ~s.~n",
[ ActualClass ] ),
% Interesting test for the stack trace, when called from the Mammal test:
%throw( exception_throw_test_from_request ),
wooper:return_state_result( RequestedState, 15 ).
% Allows to test that we can indeed call any version of the implementation of a
% method, not only the latest overridden one.
%
-spec testExplicitClassSelection( wooper:state() ) -> oneway_return().
testExplicitClassSelection( State ) ->
% Using just executeOneway( State, setAge, 20 ) would call the class_Mammal
% version, we call the class_Creature version instead, which sets the age to
% 36 regardless of the specified one:
%
NewState = executeOnewayAs( State, class_Creature, setAge, 20 ),
36 = getAttribute( NewState, age ),
wooper:return_state( NewState ).
You can’t perform that action at this time.