📄 swarm.objectbase.sgml.reference.html
字号:
>Next come the message prototypes to which this agent will respond. And it is worth noting again that these are <ICLASS="EMPHASIS">in addition to</I> those declared in the <ICLASS="EMPHASIS">SwarmObject</I> superclass. So, not only will other objects be able to send messages to this agent that are declared here, but other objects will be able to send all the messages declared in the <TTCLASS="LITERAL">objectbase/SwarmObject.h</TT> imported previously. The messages prototyped here will dictate what the compiler thinks this object can respond to. Hence, if any part of any of these prototypes differs from the corresponding function definition in the <TTCLASS="LITERAL">Heatbug.m</TT> file, then the compiler will say something like <TTCLASS="LITERAL">Object: aHeatbug does not respond to xyz</TT>, where "xyz" is the name of the message that is being sent to the <TTCLASS="LITERAL">Heatbug</TT>. A script is provided with the Swarm distribution that fixes header file prototypes to match the message declarations in the corresponding ".m" file. This script should be in the <TTCLASS="LITERAL">$SWARMHOME/bin</TT> directory and is called <TTCLASS="LITERAL">m2h</TT>. </P><P>One more thing to notice about these prototypes is that some of them are duplicates of what appears in the <TTCLASS="LITERAL">objectbase/SwarmObject.h</TT> file. This means that when the message is called on a <ICLASS="EMPHASIS">Heatbug</I> object, it will execute the method defined here and not the one in the <ICLASS="EMPHASIS">SwarmObject</I> class. In the <ICLASS="EMPHASIS">objectbase</I> library, the following messages are intended to be overridden, as necessry: <TTCLASS="LITERAL">create:, createBegin:, createEnd, customizeBegin:, customizeEnd, customizeCopy:, describe:, and getInstanceName.</TT> Each of these messages do specific things that may change from subclass to subclass of <ICLASS="EMPHASIS">SwarmObject</I>. In this case, however, we're only overriding <TTCLASS="LITERAL">createEnd</TT>. The differences between we implement it in <ICLASS="EMPHASIS">Heatbugs</I> and the default is not that significant. But, it should be pointed out that when overriding certain messages, like <TTCLASS="LITERAL">createBegin:</TT> and <TTCLASS="LITERAL">createEnd</TT>, the new method should call the superclass' version of the message, as well. This is done using the default pointer to the superclass, designated <ICLASS="EMPHASIS">super</I>. The syntax in the <ICLASS="EMPHASIS">Heatbugs</I> case is:<TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">[super createEnd];</PRE></TD></TR></TABLE> </P><P>The reasons for doing this are related to the object phase protocols used by <ICLASS="EMPHASIS">defobj</I>. If you would like more info on that, see the <AHREF="http://www.swarm.org"TARGET="_top"><ICLASS="CITETITLE">Swarm User Guide</I></A>. </P><P>Finally, the <TTCLASS="LITERAL">@end</TT> keyword signifies the end of the interface definition. GNU Objective C allows one to leave this off; but, it is not good practice.</P><P>And that's it. Of course, there're a few tricky aspects to using the <ICLASS="EMPHASIS">objectbase</I> library that weren't mentioned here. Some of them will be mentioned in the <AHREF="swarm.objectbase.sgml.reference.html#SWARM.OBJECTBASE.SGML.SECT1.ADVUSAGE">Advanced Usage Notes</A> and the <AHREF="swarm.objectbase.sgml.reference.html#SWARM.OBJECTBASE.SGML.SECT1.IMPL">Implementation Notes</A>; but, the best way to learn is to examine the way the demo applications do it and try to make some changes yourself.</P></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN11368">3.3. Subclassing from <ICLASS="EMPHASIS">Swarm</I></A></H2><P>Subclassing from the <ICLASS="EMPHASIS">Swarm</I> class works very similar to subclassing from <ICLASS="EMPHASIS">SwarmObject</I>. </P></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN11374">3.4. ActivityControl</A></H2><P>The <ICLASS="EMPHASIS">ActivityControl</I> object provides much more finely grained control over the execution of an interactive simulation. It addresses both the problems of not being able to stop the simulation at any given point in any given activity and provides an initial step towards a Swarm debugger. </P><P>An activity controller can be attached to <ICLASS="EMPHASIS">any</I> activity that is created in a Swarm simulation, including those that are created for use only by the Swarm kernel. The controller then provides the basic activity manipulation messages on that activity, which are: <TTCLASS="LITERAL">run, stop, next, step, stepUntil,</TT> and <TTCLASS="LITERAL">terminate</TT>. </P><P>The presence of the <ICLASS="EMPHASIS">ActivityControl</I> object might cause some confusion about what role the <ICLASS="EMPHASIS">ControlPanel</I> should play in the controlled execution of the various schedules. The <ICLASS="EMPHASIS">ControlPanel</I> should still be used for the top-level control of any simulation that is running in a context where <ICLASS="EMPHASIS">random</I> interference is expected (like under a GUISwarm where the user may click a button at any time). The reason this is true is because the <ICLASS="EMPHASIS">ControlPanel</I> sends pseudo-interrupts to the infinite loop we use to perpetuate execution of the top level Swarm (which can only be seen in the form of the <TTCLASS="LITERAL">go</TT> message on a <ICLASS="EMPHASIS">GUISwarm</I> at present). <ICLASS="EMPHASIS">This type of control may change in the future!</I> But, for now, it is how we monitor the control state of the simulation. </P><P>Now, having said that, the <ICLASS="EMPHASIS">ControlPanel</I> should no longer be used to run the simulation. It should only be used to instantiate the control context and quit the entire simulation. That means that sometime in the future, the <TTCLASS="LITERAL">Go</TT> and the <TTCLASS="LITERAL">Stop</TT> buttons will be removed from the <ICLASS="EMPHASIS">ControlPanel</I> display. They have been left in for backwards compatibility so that applications that do not use the new <ICLASS="EMPHASIS">ActivityControl</I> will retain their (albeit handicapped) controllability. Also, the current <TTCLASS="LITERAL">Time Step</TT> button will be renamed to <TTCLASS="LITERAL">Start</TT> to be consistent with it's new purpose. </P><P>In order to use the new control mechanism, you must place code like the following in the top-level Swarm. (This code was taken from a modified mousetrap demo app.) </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">observerActCont = [ActivityControl createBegin: [self getZone]];observerActCont = [observerActCont createEnd];[observerActCont attachToActivity: [self getSwarmActivity]];[probeDisplayManager createProbeDisplayFor: observerActCont];</PRE></TD></TR></TABLE><P>This creates an <ICLASS="EMPHASIS">ActivityControl</I> and attaches it to the top-level activity (in this case an <TTCLASS="LITERAL">observerSwarm</TT>). It also creates a display for the controller. (The probe map for the <ICLASS="EMPHASIS">ActivityControl</I> class is designed within the <ICLASS="EMPHASIS">ActivityControl</I>, itself. This is done because all of these objects are expected to look the same to any outside object.) With this activity controller, you will then be able to <TTCLASS="LITERAL">run, stop, next, step, stepUntil,</TT> and <TTCLASS="LITERAL">terminate</TT> that activity. </P><P>There are some tricky aspects to successfully using an <ICLASS="EMPHASIS">ActivityControl</I> object that the <AHREF="swarm.objectbase.sgml.reference.html#SWARM.OBJECTBASE.SGML.SECT1.ADVUSAGE"> Advanced Usage Notes</A> will cover. </P></DIV></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1"><ANAME="SWARM.OBJECTBASE.SGML.SECT1.ADVUSAGE">4. Advanced Usage Guide</A></H1><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN11413">4.1. ProbeMap design</A></H2><P>When designing a <ICLASS="EMPHASIS">ProbeMap</I> for a given (subclass of) <ICLASS="EMPHASIS">SwarmObject</I>, inclusion of instance variables or messages defined in the super class might be desirable. The normal <ICLASS="EMPHASIS">ProbeMap</I> design code might look like (this code was taken from the tutorial app called "hello-world"): </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">probeMap = [CustomProbeMap createBegin: [self getZone]];[probeMap setProbedClass: [person class]];probeMap = [probeMap createEnd];[probeMap addProbe: [probeLibrary getProbeForVariable: "room" inClass: [person class]]];[probeMap addProbe: [probeLibrary getProbeForVariable: "party" inClass: [person class]]];[probeMap addProbe: [probeLibrary getProbeForVariable: "name" inClass: [person class]]];[probeMap addProbe: [probeLibrary getProbeForVariable: "stillhere" inClass: [person class]]];[probeMap addProbe: [probeLibrary getProbeForVariable: "listOfFriends" inClass: [person class]]];[probeMap addProbe: [probeLibrary getProbeForVariable: "myColor" inClass: [person class]]];[probeLibrary setProbeMap: probeMap For: [person class]];[probeDisplayManager createProbeDisplayFor: person];</PRE></TD></TR></TABLE><P>where <TTCLASS="LITERAL">room, party, name, stillhere, listOfFriends,</TT> and <TTCLASS="LITERAL">myColor</TT> are instance variables declared in the interface to the <ICLASS="EMPHASIS">Person</I> subclass. And <ICLASS="EMPHASIS">Person</I> is a subclass of <ICLASS="EMPHASIS">Agent2d</I>, which is a subclass of <ICLASS="EMPHASIS">SwarmObject</I>. </P><P>Now let's say that there are two variables declared in <ICLASS="EMPHASIS">Agent2d</I> that you want to put into this custom probe in addition to the ones you've picked out of <ICLASS="EMPHASIS">Person</I>. Call them <TTCLASS="LITERAL">x</TT> and <TTCLASS="LITERAL">y</TT>. The way to add them to the <TTCLASS="LITERAL">probeMap</TT> is to add the following two lines of code to the above. </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">[probeMap addProbe: [probeLibrary getProbeForVariable: "x" inClass: [Agent2d class]]];[probeMap addProbe: [probeLibrary getProbeForVariable: "y" inClass: [Agent2d class]]];</PRE></TD></TR></TABLE><P>And that's it! The two superclass-declared variables, which are, in fact, instance variables of the instance of the subclass, are now included in the probe. </P><P>In addition, a convenience message has been added to the <ICLASS="EMPHASIS">CustomProbeMap</I> interface to compress the above rather cluttered mechanism into one message. This convenience message can be used in the usual case where a <ICLASS="EMPHASIS">ProbeMap</I> will consist of variables and messages from the same class. For example, the first part of the custom probe creation above can be shortened to:<TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">probeMap = [CustomProbeMap create: [self getZone] forClass: [person class] withIdentifiers: "room", "party", "name", "stillhere", "listOfFriends", "myColor", NULL];</PRE></TD></TR></TABLE> And if the user wanted messages in the probe as well, it could be extended to:<TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">probeMap = [CustomProbeMap create: [self getZone] forClass: [person class] withIdentifiers: "room", "party", "name", "stillhere", "listOfFriends", "myColor", ":", "setWorld:Room:Party:", "setPerson:Topic_array:ShowSpeech:", NULL];</PRE></TD></TR></TABLE> </P><P>At present, this message doesn't search the superclasses for the message names listed here. But, that will soon be rectified.</P></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN11441">4.2. ActivityControl Issues</A
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -