Before Flash/Flex, I wrote software in Python. There are several concepts in Zope/Plone/Python that are very relevant to Flex and ActionScript 3. Many people know about Inheritance and Composition but very few know about Acquisition. I am going to introduce the concept of Acquisition and show some examples of it within Flex. Looking back, understanding Acquisition has been a key factor in my personal success with Flash and Flex.
First things first, a warning. We are OOP off-roading here. If you bring your OOP preconceptions along they might get a little shaken up. Acquisition is a bit different but it fits seamlessly with Inheritance and Composition. You have been warned!

So lets start with a definition of Acquisition (Wikipedia doesn't have a good definition, I told ya we are offroading here!):
Acquisition - The ability of any object to acquire data and behavior from surrounding objects.
What the hell does that mean?
In its simplest form, Acquisition allows you to build objects/components that change their behavior depending on where they are located at runtime. These objects "acquire" data and behavior from surrounding objects based on composition. Acquisition takes composition to its logical next step by allowing objects to be created that react to what they are within, next to, or what objects they contain.
Confused? No getting stuck in the mud, keep the peddle down. Here are some concrete examples of Acquisition behavior within Flex:
"Child" Acquisition
TabNavigator - This container defines navigation based on its children. TabNavigator changes behavior purely based on the objects (containers in this case) that are put within it and the order they are put in. TabNavigator reads the 'label' property from its children to define tabs. The Tabs in TabNavigator are obviously part of the TabNavigator component but their data is derived directly from the children within. If you remove a child, the tab is removed, if you add a child, a new tab is created, if you change the 'label' property of a child, the tab label changes.


I like to think of this as "Child" Acquisition as the TabNavigator looks to its children to define its own data and behavior.
"Parent" Acquisition
Take a Button and change its label based on the parent container of the button. Put this Button in a Panel, it looks one way, put it in an Accordion, it looks different.


I like to think of this as "Parent" Acquisition as the component looks to its container/parent to define its data and behavior.
"Sibling" Acquisition
Take a series of buttons all with percentage height and add them into a base Application container set to vertical layout. Depending on the percentage size of each children, it affects the size of other children during measurement and layout. In this case, if the size of one child changes, so do all siblings within a container.


I like to think of this as "Sibling" Acquisition as a component depends on its siblings to define its data and behavior.
I believe that there are many details within Acquisition that can be applied to Flex directly given that both MXML and ActionScript 3 lend themselves to heavy use of Composition. From DOM Events to Constraint-based Layout to States, many Flex concepts depend on the runtime state of components and containers. What is fascinating to me is that we can go deeper and design systems of components that work within Acquisition to make Flex application development simpler, easier, and more reusable. Not that support for Acquisition is pre-defined in Flex per say, but I think there is a foundation in Flash Player 9 and Flex to build upon.
Here is where the rubber meets the road again and we go back to coding. Acquisition is a way to think about programming behavior into the components and objects we create. As objects can inspect parent, children, and siblings, it makes sense to program behavior that reacts to other components.
In classic Zope/Python, Acquisition is a pattern that defines a lookup tree based on composition. If you need a variable, you can lookup the tree of composition to find a definition if one is not defined within the current object. Instead of walking the inheritance chain, you walk up the composition chain of parents to the root. This way objects within another object don't have to define all of their behavior and that behavior can change depending on how the object is composed.
Here is the summary from the Plone Manual:
Acquisition allows behavior to be distributed throughout the system. When you add a new object to Zope, you don't need to specify all its behavior, only the part of its behavior that is unique to it. For the rest of its behavior it relies on other objects. This means that you can change an object's behavior by changing where it is located in the object hierarchy. This is a very powerful function which gives your Zope applications flexibility.
Acquisition is useful for providing objects with behavior that doesn't need to be specified by their own methods or methods found in their inheritance hierarchies. Acquisition is particularly useful for sharing information (such as headers and footers) between objects in different folders as well.
Here are some other resources on Acquisition:
Nature vs Nurture - John Udell
A new inheritance-like abstraction mechanism - Joseph Gil and David H. Lorenz
Abstract:
The class of an object is not necessarily the only determiner of its runtime behaviour. Often it is necessary to have an object behave differently depending upon the other objects to which it is connected. However, as it currently stands, object-oriented programming provides no support for this concept, and little recognition of its role in common, practical programming situations.
To give credit where credit is due, Jim Fulton of Zope deserves much credit for Acquisition, Jim wrote the initial Acquisition logic into Zope. I learned about Acquisition in working with early builds of Zope before working deeply with Flash Player. It helped me think about composition within Flash Player at runtime, defining dynamic behavior into Flash applications, and has been a key factor in my success with Flex. Call it a pattern, a tenet of OOP, environmental hoo-haa, whatever, to me Acquisition just helps me think about creating components that react to how they are organized at runtime.
In many ways Acquisition brings in the element of environment into software development and these patterns are grounded into our everyday life. My car works differently depending on the road it is on and I act differently depending on who I am around, so too with components and software. Shoot, maybe this post will be different because I wrote it on a Sunday in the comfort of my own home. :)
Cheers,
Ted :)
DIGG IT! 
Hi Ted,
Very interesting concept! You're creating an undocumented environmental dependency which might cause problems for re-use, but it is an interesting way of effectively providing a second bite an inheritance based on physical location in a UI or conceptual position within a hierarchical data structure. Will have to ponder this, but I get how it could solve a class of problems in an interesting way.
Thanks for the great posting!
this sounds a little like the Strategy pattern but inside out, instead of an object defining key pieces of its behaviour using seperate internal "strategy" objects, the strategy might actually be outside the object, ie: its parent. This is possible in the UI because all DisplayObjects have the concept of a parent, and therefore, siblings, but does not naturally happen with non-UI objects, perhaps what is needed is a standardized way to link non UI objects up in a parent-child hierarchy and then they too can acquire behaviour from their surroundings.
I think if we create an Aquisition class to handle the base 'lookups' in the Acquisition chain, this would be far more stable.
//return an instance of an object that contains this property or method
Aquisition.locate( do:DisplayObject , name:String ):Object
//determine if a property or method exists in the Acquisition chain
Acquisition.exists( do:DisplayObject, name:String ):Boolean
These would both walk the DisplayList from a passed node upward toward the root. Using this model Acquisition gives precedence to instances closer to the current target location. Although it might be handy to do the opposite as well where objects closer to the root had precedence.
In Zope/Plone acquisition things always work up the URL like so:
http://plone/this/that/theother/me
If a method is within 'theother' it takes precedence over 'that' or 'this'.
The same is true with the AVM2 DisplayList in Flash Player at runtime. The path from the root of the player to the target instance is a url of sorts as well.
ted :)
Ted, is that a picture of downtown Edmonton?
That is Grants ride! :)
I saw some Crusiers in Edmonton but the sub-zero temps pretty much rule out wet-mud or having the top down.
FYI - I have owned 2 FJ-40's.
I think this usage of Acquisition is much more prevalent one might think. It's used throughout CSS with relative positioning and relative font-size, etc.
I have used it in Actionscript a few times by creating a MovieClip that will act as a button. The TextField inside the MovieClip gets its text value from: tf.text = this._name. So the instance name of the MC determines the text on the button.
I would agree that the AS example is problematic in many instances but it worked fine in some very specific occasions.
Would you say these are instances of Acquisition or did I go off trail with these examples?
There are many cases in Flex where values are lookup-up outside of the inheiritance chain. CSS is a good example of this behavior.
Mind you I am no expert here and we are offroad, few have paved any roads here.
It is a fact that OOP makes no concession for environment when programming. Acquisition answers the "in-a", "on-a" , "beside-a" relationships where inheirtance provides "is-a" relationships.
Ted :)
Thanks for the lesson! On question:
In OO, we try not to switch on an object's type. We do this using polymorphism and dynamic dispatch. But under the acquisition paradigm, it seems inevitable to end up with code like:
if (parent is Accordion)
cornerStyle = ROUNDED
else if (parent is TabNavigator)
cornerStyle = SQUARED
One way to avoid such situations is by giving the acquired object some hooks, like isAccordion, or childShouldHaveRoundedCorners, but that's really not much of an improvement.
Is there a nice way of avoiding switching on type without adding cruft to the acquired objects?
Nice tutorial, Ted. As a user of Python/Zope/Plone for about 2 years, my ears immediately perked up when I saw mention of acquisition. Here are a few good tuts (Zope-centric) on the topic:
http://www.zope.org/Members/crazybrett/acquisition
http://www.zope.org/Documentation/Books/ZopeBook/2_6Edition/Acquisition.stx
Cliff,
What is interesting to me is that Flash Player's DisplayList (The tree within Flash Player where all visual objects are held) provides wrapping and context to components. The implementation of acquisition in Zope/Plone/Python are different but the parent/child relationships of classes of different types is present.
I think with some work and energy here we can flesh out some techniques to make implementing acquisition easier.
As a long time zope/python fan, welcome to Flex. :)
Ted,
Your example on sibling acquisition sounds more like Child-Acquisition. Shouldn't the container (Application) access the width attributes of the children and then decide on the layout logic. I was under the impression that layout will be managed by the container and it will probe into the child attributes (in this case width) to decide on the final dimensions of the children.
Adam, you said In OO, we try not to switch on an object's type. We do this using polymorphism and dynamic dispatch. But under the acquisition paradigm, it seems inevitable[...]
The problem here is that your design isn't using acquisition. If objects are going to get their corner shapes from their parents, their parents should provide the methods they will need to draw those corner shapes.
This is the exact same situation as with inheritance -- imagine rephrasing your question to ask about superclass and subclass instead of parent and child. The general answer (in both cases) is to not inherit data, but rather inherit behavior.