at:tutorial:objects
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
at:tutorial:objects [2007/07/02 11:20] – jorge | at:tutorial:objects [2007/07/10 22:29] – * tvcutsem | ||
---|---|---|---|
Line 4: | Line 4: | ||
In AmbientTalk, | In AmbientTalk, | ||
classes. Rather, they are either created ex-nihilo or by cloning | classes. Rather, they are either created ex-nihilo or by cloning | ||
- | and adapting existing objects, | + | and adapting existing objects, |
The following code illustrates the ex-nihilo creation of an object: | The following code illustrates the ex-nihilo creation of an object: | ||
< | < | ||
- | > def point := object: { | + | def Point := object: { |
- | def x := 0; | + | def x := 0; |
- | def y := 0; | + | def y := 0; |
- | def init(aX,aY) { | + | def init(aX,aY) { |
- | x := aX; | + | x := aX; |
- | y := aY; | + | y := aY; |
- | }; | + | }; |
- | def sumOfSquares() { x*x + y*y }; | + | def sumOfSquares() { x*x + y*y }; |
- | } | + | } |
</ | </ | ||
- | As all definitions in AmbientTalk, objects, fields and methods are defined using the **def** keyword. Fields are defined using a '' | + | The above code defines an // |
- | <note important> | + | In the example above, the state of the point object is composed of '' |
- | AmbientTalk not only supports traditional canonical syntax (e.g. '' | + | |
- | </ | + | |
- | In the example above, the state of the '' | + | < |
+ | As already explained in the [[at: | ||
+ | |||
+ | For Smalltalk/ | ||
+ | </ | ||
===== Sending messages ===== | ===== Sending messages ===== | ||
Line 32: | Line 34: | ||
< | < | ||
- | > point.x | + | > Point.x |
- | >>2 | + | >>0 |
- | > point.sumOfSquares() | + | > Point.sumOfSquares() |
- | >>13 | + | >>0 |
</ | </ | ||
- | This code shows two messages sent to the '' | + | This code shows two messages sent to the point object defined above. The '' |
+ | |||
+ | Note that the " | ||
===== Cloning and instantiation ===== | ===== Cloning and instantiation ===== | ||
- | As said before in this section, AmbientTalk objects are created [[objects# | + | As noted above, AmbientTalk objects are created [[# |
< | < | ||
- | > def anotherPoint := point.new(2,3) | + | def anotherPoint := Point.new(2,3) |
</ | </ | ||
- | Every object understands the message '' | + | Every object understands the message '' |
- | ===== Delegation and cloning ===== | + | < |
- | AmbientTalk features object inheritance or delegation. By means of delegation, an object can reuse and extend the defintion of another establishing a parent-child relationship. We identify two kinds of delegation relationships: **IS-A** and **SHARE-A**. These relationships define two different semantics for clonning child objects. Whereas clonning a **IS-A** child also clones its parent, **SHARE-A** child shares the parent of the cloned object (see the figure below). | + | > anotherPoint.x |
+ | >> 2 | ||
+ | > Point.x | ||
+ | >> 0 | ||
+ | > anotherPoint.x | ||
+ | >> nil | ||
+ | > Point.x | ||
+ | >> 0 | ||
+ | </ | ||
- | {{:at: | + | < |
+ | AmbientTalk' | ||
+ | </ | ||
- | The following code shows how to extend objects with a **IS-A** relationship. It uses the '' | + | AmbientTalk also provides |
< | < | ||
- | > def point3D | + | def clonedPoint |
- | def z := 0; | + | > clonedPoint.x |
- | def sumofsquares() { | + | >> 0 |
- | super.sumofsquares() + z*z | + | > clonedPoint.x |
- | } | + | >> nil |
- | } | + | > Point.x |
+ | >> 0 | ||
</ | </ | ||
- | The following code shows how to extend | + | ===== Delegation and Cloning ===== |
+ | |||
+ | In order to support code reuse and modular extensions between | ||
+ | |||
+ | Delegation implies that, if a message is sent to an object, but that object has no definition for the message' | ||
+ | |||
+ | AmbientTalk distinguishes between | ||
+ | |||
+ | An **IS-A** delegation | ||
< | < | ||
- | > def point3D | + | def Point3D |
- | def z := 0; | + | def z := 0; |
- | def sumofsquares() { | + | def sumOfSquares() { |
- | super.sumofsquares() + z*z | + | super^sumOfSquares() + z*z |
- | } | + | }; |
- | } | + | } |
</ | </ | ||
- | ===== Delegation and dynamic inheritance ===== | + | In this example, '' |
- | The parent of an object is bound to a field named '' | + | |
+ | A **SHARES-A** relationship between two objects | ||
+ | |||
+ | The following code shows how to extend objects with a **SHARES-A** delegation relationship. It uses the '' | ||
< | < | ||
- | > def OpenConnection | + | def Collection := share: Enumerable with: { |
- | def ClosedConnection | + | def elements := []; |
- | def Connection | + | ... |
- | def open() { | + | } |
- | super := OpenConnection.new(); | + | </code> |
+ | |||
+ | In this code example, the '' | ||
+ | |||
+ | The **IS-A** and **SHARES-A** delegation relationships differ in their semantics for cloning child objects. Whereas cloning an **IS-A** child also clones its parent, a **SHARES-A** child shares its parent object with the clonee (see the figure below). | ||
+ | |||
+ | {{: | ||
+ | |||
+ | This cloning semantics reinforces the semantics of **IS-A** as promoting a unique link between a parent and a child object. **IS-A** delegation most closely corresponds to class-based inheritance. | ||
+ | |||
+ | ===== Delegation and Dynamic Inheritance ===== | ||
+ | |||
+ | In AmbientTalk, | ||
+ | |||
+ | Because '' | ||
+ | |||
+ | < | ||
+ | def openConnection | ||
+ | def send(msg) | ||
+ | }; | ||
+ | def closedConnection | ||
+ | def send(msg) | ||
+ | }; | ||
+ | def connection | ||
+ | def init() { | ||
+ | super := closedConnection; | ||
+ | }; | ||
+ | | ||
+ | super := openConnection; | ||
+ | }; | ||
+ | def close() { | ||
+ | super := closedConnection; | ||
+ | }; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | In the above example, the '' | ||
+ | |||
+ | < | ||
+ | In AmbientTalk, | ||
+ | </ | ||
+ | |||
+ | ===== First-class Delegation ===== | ||
+ | |||
+ | AmbientTalk provides a special message-sending operator '' | ||
+ | |||
+ | < | ||
+ | def Enumerable := object: { | ||
+ | def collect: closure { | ||
+ | def c := clone: self; | ||
+ | self.each: { |v| | ||
+ | c.add(closure(v)) | ||
}; | }; | ||
- | | + | }; |
- | | + | }; |
+ | def Array := object: { | ||
+ | def elements := []; | ||
+ | | ||
+ | def collect: closure { | ||
+ | Enumerable^collect: | ||
+ | }; | ||
+ | def each: clo { | ||
+ | 1.to: elements.length do: { |i| | ||
+ | clo(elements[i]) | ||
}; | }; | ||
- | } | + | }; |
+ | }; | ||
</ | </ | ||
- | ===== First-class Delegation ===== | + | A message sent to an object using the '' |
+ | Of course, the example above is a bit contrived: we could have just assigned '' | ||
+ | |||
+ | Having described the semantics of '' | ||
+ | |||
+ | < | ||
+ | def Point3D := extend: Point with: { | ||
+ | def z := 0; | ||
+ | def init(aX, aY, aZ) { | ||
+ | super^init(aX, | ||
+ | z := aZ; | ||
+ | }; | ||
+ | }; | ||
+ | </ | ||
+ | |||
+ | <note warning> | ||
+ | AmbientTalk, | ||
+ | |||
+ | Keep in mind, however, that '' | ||
+ | </ | ||
===== Encapsulation ===== | ===== Encapsulation ===== | ||
- | In AmbientTalk, all fields and methods are " | + | |
+ | AmbientTalk | ||
< | < | ||
- | > def makeObject(hidden) { | + | def makeBankAccount(balance) { |
- | object: { | + | object: { |
- | def foo() { /* use hidden */ } | + | def deposit(amnt) { |
- | } | + | balance := balance + amnt; |
+ | " | ||
+ | }; | ||
} | } | ||
+ | } | ||
</ | </ | ||
- | Due to the encapsulation of this object the following | + | Because |
< | < | ||
- | > makeObject(5).hidden; | + | > makeBankAccount(100).balance; |
- | >> | + | >> |
< | < | ||
</ | </ |
at/tutorial/objects.txt · Last modified: 2013/05/17 20:23 by tvcutsem