User Tools

Site Tools


at:tutorial:modular

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
at:tutorial:modular [2011/05/23 13:46]
tvcutsem
at:tutorial:modular [2013/05/17 20:24] (current)
tvcutsem adjusted
Line 119: Line 119:
  
 In this section, we describe how the ''import'' statement can also be used to compose multiple objects. In this respect, objects can be regarded as //traits//. [[http://www.iam.unibe.ch/~scg/Research/Traits|Traits]] are a model of object-oriented software composition, similar to (but more advanced than) mixins. A trait can be regarded as a kind of abstract class, which does not define any state, which //provides// a set of methods and which //requires// a set of methods in order to be instantiated. In a class-based language, a class may //use// one or more traits. The class takes on the role of compositor and is responsible for ensuring that, once all traits have been imported, each trait its required interface is provided by the class or other imported traits. A trait is almost literally a piece of code which can be "copy-pasted" into a class. In this section, we describe how the ''import'' statement can also be used to compose multiple objects. In this respect, objects can be regarded as //traits//. [[http://www.iam.unibe.ch/~scg/Research/Traits|Traits]] are a model of object-oriented software composition, similar to (but more advanced than) mixins. A trait can be regarded as a kind of abstract class, which does not define any state, which //provides// a set of methods and which //requires// a set of methods in order to be instantiated. In a class-based language, a class may //use// one or more traits. The class takes on the role of compositor and is responsible for ensuring that, once all traits have been imported, each trait its required interface is provided by the class or other imported traits. A trait is almost literally a piece of code which can be "copy-pasted" into a class.
 +
  
 ==== import as trait composition ==== ==== import as trait composition ====
Line 162: Line 163:
   };   };
   def each: clo {   def each: clo {
-    start.to: end do: clo+    start.to: end-1 do: clo
   };   };
 }; };
Line 183: Line 184:
 So, ''import'' defines small methods which delegate the request to the original trait (using AmbientTalk's support for [[:at:tutorial:objects#first-class_delegation|explicit delegation]]). The use of delegation is crucial here: it means that within the context of the trait, ''self'' is bound to the object using the trait. Hence, when ''reject:'' is invoked on a ''Range'' object, ''Enumerable'''s ''self.each:'' will refer to the correct implementation of ''Range''. So, ''import'' defines small methods which delegate the request to the original trait (using AmbientTalk's support for [[:at:tutorial:objects#first-class_delegation|explicit delegation]]). The use of delegation is crucial here: it means that within the context of the trait, ''self'' is bound to the object using the trait. Hence, when ''reject:'' is invoked on a ''Range'' object, ''Enumerable'''s ''self.each:'' will refer to the correct implementation of ''Range''.
  
-Note that in AmbientTalk, a trait does not need to explicitly specify the set of methods which it "requires" from its composite. However, for documentation purposes, it is often very useful to explicitly state the methods on which a trait depends. One may do so by defining those methods in the trait, and annotating them with the ''@Required'' type tag (which is predefined in the ''lobby.at.types'' module). These methods will //not// be imported when the trait is used by a composite object (otherwise they would cause a conflict with the real implementation methods in the composite). Below is an example of how the ''Enumerable'' trait can be modified to explicitly state its required methods:+Note that in AmbientTalk, a trait does not need to explicitly specify the set of methods which it "requires" from its composite. However, for documentation purposes, it is often very useful to explicitly state the methods on which a trait depends. One may do so by defining those methods in the trait, and annotating them with the ''@Required'' type tag (which is predefined in the ''lobby.at.lang.types'' module). These methods will //not// be imported when the trait is used by a composite object (otherwise they would cause a conflict with the real implementation methods in the composite). Below is an example of how the ''Enumerable'' trait can be modified to explicitly state its required methods:
  
 <code> <code>
Line 291: Line 292:
  
 In the [[at:tutorial:actors|chapter on actors]] we use this feature to distinguish purely asynchronous message sends from so-called //future-type// message sends. If the message send is annotated with the ''FutureMessage'' type tag, the asynchronous send returns a future, otherwise it returns ''nil''. In the [[at:tutorial:actors|chapter on actors]] we use this feature to distinguish purely asynchronous message sends from so-called //future-type// message sends. If the message send is annotated with the ''FutureMessage'' type tag, the asynchronous send returns a future, otherwise it returns ''nil''.
 +
  
 ===== Exception Handling ===== ===== Exception Handling =====
Line 314: Line 316:
 </code> </code>
  
-Note that a new instance of an object named ''XDivisionByZero'' is raised, not the type tag ''DivisionByZero'' itself. An exception is any object that is tagged with (a subtype of) the ''lobby.at.types.Exception'' type tag. By convention, an exception should have the fields ''message'' and ''stackTrace''. The exception module found under ''lobby.at.exceptions'' contains an auxiliary function named ''createException'' which takes a type tag as argument and returns a new prototype exception object. For example:+Note that a new instance of an object named ''XDivisionByZero'' is raised, not the type tag ''DivisionByZero'' itself. An exception is any object that is tagged with (a subtype of) the ''lobby.at.lang.types.Exception'' type tag. By convention, an exception should have the fields ''message'' and ''stackTrace''. The exception module found under ''lobby.at.lang.exceptions'' contains an auxiliary function named ''createException'' which takes a type tag as argument and returns a new prototype exception object. For example:
  
 <code> <code>
-deftype DivisionByZero <: lobby.at.types.Exception; +deftype DivisionByZero <: lobby.at.lang.types.Exception; 
-def XDivisionByZero := lobby.at.exceptions.createException(DivisionByZero);+def XDivisionByZero := lobby.at.lang.exceptions.createException(DivisionByZero);
 </code> </code>
  
Line 374: Line 376:
 def contains(tbl, elt) { def contains(tbl, elt) {
   { |return|   { |return|
-    1.to: tbl.length + 1 do: { |i|+    1.to: tbl.length do: { |i|
       if: (tbl[i] == elt) then: {       if: (tbl[i] == elt) then: {
         return(true)         return(true)
at/tutorial/modular.1306151207.txt.gz · Last modified: 2013/02/26 15:52 (external edit)