text:
This blog contains current and previous theories that are still considered SPECULATION!
- Information updated on a regular basis and is subject to changes.
- Other blogs of interest can be read here:
New True Ending All Along
A few hours ago an anonymous user who leaked the multiplayer DLC (just an hour earlier) has claimed that the ending fiasco was deliberate because of the game's storyline being leaked. They changed it so they could have more time to prepare the real ending DLC.
It is called "The Truth", and will be released in April or May… You will be able to continue your story if you picked any of the endings. Your decision during the sequence will have a big effect on the ending of The Truth. Also, The Truth adds two new sets of enemies, new classes, and multiplayer maps, including "Firebase Hive", which is a small area of the last remaining Collector Ship included in the DLC, which, by the way, you should definitely bring Javik the Prothean along if you have them.
The following picture shows some of the leaked multiplayer classes and races. One race that isn't shown is the Prothean Adept and Vanguard. This DLC also, enables the ability for owners of the preorder and From Ashes DLC to find their DLC weapons in reinforcement packs.
All of that content, and this might as well be labelled an expansion.
And it's Free!
According to Bioware's Community Manager Jennifer Merizan this is a false rumor.
The source of this information can be found here (LINK)
THIS THEORY IS NOW DEBUNKED AND PROVEN FALSE Confirmation can be seen here: https://twitter.com/#!/masseffect/status/181035997151232000
- The multiplayer leak has been confirmed as true and was announced as free during PAX 2012.
'Harbinger/Child in game model theory'
Harbinger/Child in game model theory: Because of leaks being the cause of all this nonsense I will not be going into specifics just yet. Specific specialized PC software tools can be used to do this and I am not going to say which as it constitutes a breach of the user licence to do so. (Note: I was not the one that did it).
Anyways, somebody claimed to have used a model viewer on the game files and there's actually some hard proof that the Indoctrination theory might be true, or at least might have been true sometime in development.
The image in question was this: http://i.imgur.com/TywdI.png
However, this is not true and the image was altered by someone with too much time on their hands. The actual image is this: http://i.imgur.com/r6xuQ.png
Credit goes to Cygnus888 for clarifying this.
'Liara waking Shepard'
A recently released photo may also back up this claim in some shape or form as well Leaked Image.
- Confirmed fake:
Bioware are listening about it now and have asked people to voice there opinion on the BioWare forum thread so they know how to shape their response. Please go on their and voice what you thought is needed or show your support for another person's idea that you agree with. Link here:http://social.bioware.com/forum/1/topic/355/index/9992961
Ignore all supposed leaks because that started this fiasco in the first place (I know this is hypocritical since this is a blog about a leak) and voice your opinion on the endings and how you want it to end. They want to hear from you now and this is because they are listening and willing to do something to fix this. It may have been planned all along, it may not, but you can be assured that BioWare are thinking about the satisfaction of their fan base too and you will not be disappointed.
The following blog contains links to comprehensive polls and the feedback section on the BioWare Social Network.
Keep the pressure up because if you do and it's true then Bioware will likely make it a free DLC, if it isn't then they will at least know the DLC is needed by the fanbase!
Until then, Remember, HOLD THE LINE! Demand better endings!Sign the facebook campaign because it is for charity too!
Link here: http://social.bioware.com/forum/1/topic/324/index/10089946
In response to this the fans have set up this page so read the first post and the advice given.
1) Very Important Link: http://social.bioware.com/forum/1/topic/355/index/10084349/1
After reading the 1st post of the above link (1) use the second link to respond.
2) Official Suggestions: http://social.bioware.com/forum/1/topic/355/index/10098213/1
3) Sign the Facebook Campaign: Demand a Better Ending Petition on Facebook.
RetakeME3 Campaign
RetakeME3 has started a letter campaign if anyone wants to join in. There's nothing like a good old fashioned letter campaign. Physical letters can often mean a lot more than digital ones. I'd like everyone who is willing and able to compose a letter to send to Bioware (just them for the moment).
Letters need to be short, and simple. Highlight why you are writing to them, and what you are asking for. Do not suggest ideas for a new ending other than in vague terms.
BE POLITE AND COURTEOUS. If it wouldn't be in a Disney cartoon it shouldn't be in your letter.
Retake are asking any fan who wishes to have clarification to send out their letters and emails on the 26th of March.
add: #RetakeMassEffect somewhere in your letter, so they know we are all in this together.
Can't send a physical letter? Email works, same rules as above.
Where to send: Mailing Address:
- BioWare Edmonton
- 200-4445 Calgary Trail NW
- Edmonton AB
- Canada T6H 5R7
and you can contact BioWare via this email.
Email: firstname.lastname@example.com
RetakeME3 Campaign Website: http://www.retakemasseffect.org/
It also reminds me of a quote I once read and I feel it is appropriate for this situation and sums up my feelings.
There is nothing so well known as that we should not expect something for nothing - but we all do and call it Hope. Edgar Howe
Important Video Updates
Finally I would like to link four videos that I feel the community will find very interesting. The first 3 videos are long but truly they are worth the time it takes to watch them. I highly recommend that people watch the first three videos in order as they expand on the series, its origins and the stages at which it changed
Storyline Videos
- This first link is to a video by a developer on the original concept for Mass Effect by Drew Karpyshyn and the potential for fixing the story as it is.
- This following video was in response to the overwhelming response to the first video of Drew Karpyshyn's initial story idea and potiential ways of salvaging the endings. This video focuses on the Illusive Man's role and the overall role of Cerberus in Mass Effect.
- This final video of the 3 relates to the Indoctrination Theory, the future of BioWare and the Importance of Choice as a core theme of the Mass Effect series. This video also looks at the stress and strain put on developers during one of the most ambitious projects in gaming development so far. A nice touch in allowing the fans to appreciate the realities facing the people behind the scenes.
Indoctrination Theories and GroupThink
- The following videos show the most popular fan theories for the Indoctrination Theory.
- An interesting article arguing against the Indoctrination Theory that is worth a read. It provides a logical breakdown and analysis of real world and in game events and puts forward a strong case that this theory is a fan made one (though good) which is severely flawed.
- Here is another video arguing against the Indoctrination Theory which builds on a previous video with regards to the inconsistencies in the endings produced by BioWare.
- The following videos deconstruct the entire game, its place in the series and the endings. The videos also crafts arguments that point out the logical faults in the Indoctrination Theory. There are some continuity errors in the videos narrators arguments but he address them later in the video.
As we all are aware of now, PEnny Arcade Expo (PAX) is taking place in Boston from the 6th - 8th of April. Many different game developers and companies will be there but more importantly the BioWare/Mass Effect 3 Panel will be taking questions etc.
- The following list has details on the PAX panel and other relevant items;
- The PAX site has confirmed that Casey Hudson will not be there.
- This list they give includes
- Chris Priestly (Community Manager),
- Mike Gamble (Producer),
- Corey Gaspur (Combat Designer),
- Patrick Weekes (Writer),
- John Dombrow (Writer),
- Reid Buckmaster (Quality Assurance).
The event itself will be broadcat on GameSpot and I will update once a link becomes available.
Here is a link to potiential places it can be watched online.
- Link.
PAX panel audience recording
New longer videos from PAX uploaded by a member of the audience. (all videos are in sequence one after the other.
I will update with more as they become available.
No New Endings
There is an article in today's (2nd April) newspaper Reforma in Mexico about the ME3 ending controversy.
Daniel Gonzalez, director of marketing and public relations for EA Latin America, says that they will release no DLC with a different ending. There will be a epilogue DLC to better explain the details of the ending, which will cost this minority of players but the ending will remain the same.
Regarding the future of the franchise, he declared that ME3 was the end of Shepard but not the end of the game, and promised that news about more MP DLC would be forthcoming in two weeks' time.
I don't think that leaves an awful lot of room for interpretation. For anyone who was hoping for a different ending and not a clarification of the dreadful current one, it doesn't look good.
- The following link has more details on this new development.
Personally, I think we should wait until PAX before coming to any conclusions. This could simply be an out of touch Executive spouting gibberish and trying to save face or it could be that he doesn't know what BioWare are planning and is responding like so many others who are not fully aware of the facts. I'm going to wait unttil BioWare has at least address/touched on the topic at PAX.


text:
Summer has ended, and with it wedding season. The number of gigs I've been playing each week is now returning to a level more compatible with two other jobs and a master's degree. Now I have time to take stock and update you on my two new working guitars…
My previous Strat, one of the new Fender Made in Mexico Standards, featured coil-tapping on both the neck & bridge pickups. In my current function band, I found myself playing it almost exclusively in the single-coil setting. After years of having a humbucker in the bridge position, I finally fell in love with the classic single-coil Strat sound. As it turned out, the Mexican Strat's neck didn't feel quite right for me – a trifle too thick, certainly compared to the thinner, vintage feel of my favourite blue Strat (see 'Gear Talk' 1 & 2). At the same time, I'd read several reviews singing the praises of the top-end Squier models. It seemed that Squier were no longer solely the savvy choice for the beginner.
I'd been looking for two guitars which sound and feel similar enough to each other to make mid-gig changes much smoother. The weight and shape/feel of the neck needed to feel close to identical, while the sound had to match up as best as it could. I had also been hoping to use more budget-concious instruments – if the build quality was up to it – in order to retire my favourite blue Strat from regular function gigs. On paper, the squires seemed ideal, so I took the plunge and bought two varying models on a retro theme…
Squier Vintage Modified Stratocaster
The rave reviews on the deluxe, Classic Vibe and new Vintage Modified lines claimed that many guitarists might well be fooled in a blindfold test with some of Fender's classic guitars. Likewise, build quality and parts were considered by some to surpass the recent Mexican standards. With this in mind, I purchased a brand new Squier Vintage Modified Strat, finished in a quote lovely custard yellow colour they call Vintage Blonde.
The Vintage Modified range aims to replicate a vintage guitar that's been retro-fitted with player upgrades. Here, that means Duncan-designed pickups, a better bridge than the entry-level Squiers, a thin, tinted neck and vintage style tuners for better stability. The pickups appear to be a slightly aged off-White, adding to the retro vibe. Best of all (in my opinion), it has the large headstock that Fender started using in the last sixties/early seventies, which is the most obvious nod to the past.
I really like the sound of this guitar. And that's not compared to Squier's Affinity range, but the Mexican standards. The basswood body is lighter, but it doesn't have an obvious effect on either the sound or sustain if this guitar, even compared to my Blue Mexican. Likewise the feel, not to mention the incredible playability, of this guitar far exceed its humble price tag. This has become my main axe for function work. All I needed now was a similar beast to partner it with…
Classic Vibe Simon Neil Stratocaster
I'm going to come clean here and admit I'd never heard of Simon Neil. While I had heard of his band, Biffy Clyro, I couldn't name or even recognise a single song of theirs, nor could I adequately describe their style. However, friends more clued up on this sort of thing than I am informed me they have a mix of street cred with a younger audience and play interesting, heavy rock music. The specs on this guitar imply that Mr Neil has good, and indeed similar, taste in guitars to me. While I wouldn't normally buy a signature model (other than a Les Paul, naturally), seeing this guitar going for £200 second hand was too good an opportunity to pass up. Heck, if I didn't like it, I could always sell it on.
This (now discontinued) guitar is essentially a budget-friendly version of the Fender Simon Neil signature model. Based on a '62 Strat in gorgeous Fiesta Red, it certainly looks the part. The Mark Knophler/early Hank Marvin vibe in the aesthetic was enough to override any boggling doubts about the subtle Biffy Clyro logo on the headstock. The rosewood fingerboard is slightly lighter than expected, but sounds as warm and dark as you'd expect. As with the Vintage Modufied guitar, the bridge and tuners are an upgrade from those axes at the lower end of the Squier range, and the overall build quality feels like another great job from their Chinese factory. The pickups are a custom mix of Alcino 3 and 5 magnets, which offer up a delightful blend of early and late 60's Strat tones in one guitar. Very nice!
Having played this guitar for a couple of weeks now, I feel it's here to stay. I'm currently setting it up so it's gig-ready, as the action on the two guitars wasn't quite matching up. There is a slight difference in the sound, particularly when overdriven, but it's close enough to be complimentary. Other than that, and the obvious differences in finish, these guitars feel the same in my hands and under my fingers, which is exactly what I was looking for.
Finally, even though I never thought I'd say this, I encourage you to give Squier (and indeed other budget models) a go before spending all your money on the top-end guitar brands. Now, more than ever, you may well find the difference is that you're paying extra for the name. All in, these two new guitars cost less than one New Mexican standard, and for what I need as a working musician, they do the job exceedingly well. Join us, and you too can live the two Squier dream onstage!

subset: commoncrawl


text:
2007 Sponsor & Partner Directory
Presenting Sponsors |
Platinum Sponsors |
Gold Sponsors |
Bronze Sponsors |
Contributing Sponsors | Showhouse Sponsors | Major Partners | Media Partners | Outreach Partners | Educational Sponsors
Presenting Sponsor
Homeowner Day Presented by: PG&E
The Pacific Energy Center offers educational programs, design tools, advice, and support to create energy efficient buildings and comfortable indoor environments. Most of our efforts are focused around commercial buildings; however, other departments offer advice and information for residential buildings.
Platinum Sponsors
Environmental Protection Agency (EPA) Region 9
EPA's Region 9 office works to protect public health and the environment in the southwestern United States (Arizona, California, Nevada, and Hawaii).
Visit us to learn more about EPA's green building programs.
City of San Francisco
San Francisco's Department of the Environment
SF Environment's mission is to improve, enhance, and preserve the environment and to promote San Francisco's long-term environmental well being.
Build It Green
Build It Green is a professional non-profit organization whose mission is to transform the building industry so that buildings are remodeled and built using green practices and products.
Build It Green is the Producer of the first Green Home Tour in San Francisco – click here for more info
Sensible City
Sensible City is a marketing & PR firm which executes profitably-designed, purpose-powered community outreach programs. Sensible City clients fuse the economics of abundance with tactical business development, enabling a culture of servant leadership and consistent, extraordinary results.
Webcor Builders
Webcor Builders is currently ranked by volume as the largest contractor in California. More than 35 years of working for such clients as Lucasfilm, California Academy of Sciences, eBay, Oracle Corporation, Symantec and Starwood Lodging has secured its position as a builder for corporate campuses and high-profile, large-scale projects. Through the years, Webcor has become known for its innovative and efficient approach to construction, wide range of experience, skill in concrete construction and expertise in the use of technology. Webcor takes an active role in its projects by providing both cost-effective solutions during the preconstruction period and leadership during the construction phase, ensuring that its clients receive the high level of quality and service they expect. Webcor is consistently listed among the ENR Top 30 General Contractors in the Nation and currently has more than $1.8 billion of contracts in place.
Gold Sponsors
TerraMai - Reclaimed Woods from Around the World
TerraMai provides beautiful, distinctive lumber and flooring products made exclusively of reclaimed wood from around the world. TerraMai sources wood from buildings and structures slated for demolition as well as packing material and orchard salvage destined for the landfill. Founded in 1991, TerraMai has provided premium wood for projects ranging from Patagonia retail stores to the Baltimore Aquarium and the San Francisco Conservatory of Flowers and reclaimed millions of board feet of old-growth lumber.
Sun Light & Power
Sun Light and Power is a certified green business specializing in the design and installation of residential and commercial solar energy systems, both photovoltaic (solar electricity) and thermal (solar hot water), with over 30 years of experience and hundreds of installations throughout the greater San Francisco Bay Area.
Bronze Sponsors
Alameda County Waste Management Authority
Integrity from Marvin Windows and Doors
Integrity from Marvin Window and Doors employ stewardship values that respect and deploy a sense of responsibility for the environment. We pride ourselves on developing and supporting sound environmental business practices and products. Integrity is constructed of Ultrex, a pultruded fiberglass that has a longer life-cycle due to characteristics like 8x the strength of vinyl, 5x longer UV resistance than vinyl, 39% less energy required to produce than vinyl, and is made primarily of silica sand-an abundant natural resource. Ultrex is manufactured in the only pultrusion facility to fully comply with the 1990 Clean Air Act, and Integrity was recognized as the 2005 Greener North Dakota Company of the Year.
Timbron's mission is to be a leader in recycling waste plastics and manufacturing quality products with a purpose: to protect and enhance our environment.
NCFI Polyurethanes
LP Building Products
LP® TechShield® Radiant Barrier is one of the most cost-effective measures for improving home energy savings throughout California's various microclimates, regardless of other conservation measures installed. LP TechShield reduces attic temperatures up to 30 degrees which results in home energy savings of up to 20% and increased home comfort.
We believe:
- The materials you select for your home or project reflect your style and your values.
- Following sustainable building practices is the only responsible method of new building design and construction.
- Mining a non-renewable resource like virgin stone to create building material is a destructive, unsound practice.
We believe there's a better way. We're dedicated to providing an eco-friendly alternative to granite, quartz, and other quarried stone – an alternative that's both gorgeous AND good.
Canadian Consulate
California Energy Commission
The New Solar Homes Partnership (NSHP) is part of Governor Arnold Schwarzenegger's California Solar Initiative (CSI ). The NSHP merges the goals of energy efficiency and solar production to accomplish the installation of 400 megawatts (MW) of solar electric systems on energy efficient new homes in California over the next ten years. The Energy Commission will partner with builders and developers to create a self-sustaining market for solar homes that incorporate high levels of energy efficiency and high-performing systems on 50 percent of new homes by the end of that period. The NSHP program will target new residential construction, both single family and multi-family, including affordable housing. The NSHP provides incentives based on the system's expected performance plus technical and market support for builders participating in the program. The program officially began on January 2, 2007.
Contributing Sponsors
New Resource Bank
Supex Bond
Special Hardwood
Dunn Edwards Paint
Dupont - Orepac
Klip Bio Technologies
US West Energy Solutions
SG Blocks
Quality Custom Components
NanaWall® all custom operable glass wall systems combine energy efficient, weathertight security with the ability to instantly and easily fold wide open. Stringent independent testing insures that the NanaWall meets the most challenging architectural specifications and LEED performance criteria.
NanaWall Combines LEED friendly materials with LEED project standards such as daylighting and natural ventilation. The NanaWall is NFRC rated and EnergyStar certified. Custom sizes, configurations, hardware, and glazing insure inspired design and long-term product satisfaction.
Trendsetter Solar Products
Showhouse Sponsors
Major Partners
Green Technology
Green Technology is a non-profit initiative with a mission to assist government sustainability efforts, providing a forum in which government officials can communicate with colleagues and with those in the private sector who are developing and distributing green technologies. It accomplishes this mission through publishing, including Green Technology Magazine, and through organizing events such as the Green California Summit and the Green California Schools Summit.
Michelle Kaufmann Designs
Michelle Kaufmann Designs is a full service architectural + design firm that is 100% committed to creating healthy, sustainable homes and buildings that are as beautiful as they are green.
Xtreme Homes
Economic Transformations Group
The Grove
Sunset Magazine
Media Partners
Outreach Partners
Greenspace is a 4000 sf store, showroom and education center specializing in green products for the home and business, providing a wide array of green products. Greenspace works with designers, contractors and the general public to provide high quality, eco-friendly solutions for home, business and building projects.
3EStrategies is a Bend Oregon-based sustainability non-profit working in the areas of Green Building and Climate & Energy. The Building Green Council of Central Oregon provides education and assistance to regional design professionals, residents, communities and local governments as part of its mission to "make green building the norm."
Acterra is a non-profit based in Palo Alto, California. Acterra was formed in 2000 by the merger of two of the region's most respected and effective environmental organizations: the Peninsula Conservation Center Foundation (founded in 1970) and Bay Area Action (formed in 1990). Their mission is to create local solutions that foster a healthy natural environment.
The American Society of Interior Designers
A community of designers, industry representatives, students and educators which has an innovative understanding of we beings interact with our environment.


text:
The upcoming calendar is currently empty.
Click here to view past events and photos »
AlumNews is Oklahoma Christian's way to keep you, our alumni, up to date with each other and the University by sharing news about the many exciting things happening here and in the lives of our alumni.
In addition to being the home of exciting campus news updates, AlumNews is also the home of Milestones. What are Milestones? We're glad you asked. Milestones are the important events in your life that you share with other alumni.
Not sure what to submit? Most of the Milestones we receive fall into one of the following categories: Births and Adoptions, Career Accomplishments, Condolences, Weddings, and General News. If it's important to you, it belongs in Milestones!
Whether you've just won the Nobel Peace Prize or moved to Noble, Oklahoma, Milestones is the place to go to share your news with friends and classmates!
Click here to submit your own Milestone to be included in AlumNews.
Remember Me
8/13/20191988- Dan and Angi (Roper) Lovejoy
7/22/20192019- Bobby and Danae (Johnston) Edwards
7/17/20191977-2010 Antine Family


text:
I have made a class file in my plugin folder. Then I wrote,
class Sample{
function footer_content(){
echo "show any data";
Then I added the function footer_content to wordpress footer by using add_action command. But it didn't show anything. maybe I am missing something in this, as it is not working.
add_action('wp_footer', Sample::footer_content());


text:
Ada Programming/Object Orientation
- 1 Object orientation in Ada
- 1.1 The simplest object: the Singleton
- 1.2 Primitive operations
- 1.3 Derived types
- 1.4 Type extensions
- 1.5 Overriding
- 1.6 Polymorphism, class-wide programming and dynamic dispatching
- 1.7 Creating Objects
- 1.8 More details on primitive operations
- 1.9 New features of Ada 2005
- 1.10 Abstract types
- 1.11 Multiple Inheritance via Interfaces
- 1.12 Multiple Inheritance via Mix-in
- 2 Class names
- 3 Object-Oriented Ada for C++ programmers
- 4 See also
Object orientation in AdaEdit
Object oriented programming consists in building the software in terms of "objects". An "object" contains data and has a behavior. The data, normally, consists in constants and variables as seen in the rest of this book but could also, conceivably, reside outside the program entirely, i.e. on disk or on the network. The behavior consists in subprograms that operate on the data. What makes Object Orientation unique, compared to procedural programming, is not a single feature but the combination of several features:
- encapsulation, i.e. the ability to separate the implementation of an object from its interface; this in turn separates "clients" of the object, who can only use the object in certain predefined ways, from the internals of the object, which have no knowledge of the outside clients.
- inheritance, the ability for one type of objects to inherit the data and behavior (subprograms) of another, without necessarily needing to break encapsulation;
- type extension, the ability for an object to add new data components and new subprograms on top of the inherited ones and to replace some inherited subprograms with its own versions; this is called overriding.
- polymorphism, the ability for a "client" to use the services of an object without knowing the exact type of the object, i.e. in an abstract way. Indeed at run time, the actual objects can have different types from one invocation to the next.
It is possible to do object-oriented programming in any language, even assembly. However, type extension and polymorphism are very difficult to get right without language support.
In Ada, each of these concepts has a matching construct; this is why Ada supports object-oriented programming directly.
- Packages provide encapsulation;
- Derived types provide inheritance;
- Record extensions, described below, provide for type extension;
- Class-wide types, also described below, provide for polymorphism.
Ada has had encapsulation and derived types since the first version (MIL-STD-1815 in 1980), which led some to qualify the language as "object-oriented" in a very narrow sense. Record extensions and class-wide types were added in Ada 95. Ada 2005 further adds interfaces. The rest of this chapter covers these aspects.
The simplest object: the SingletonEdit
package Directory is function Present (Name_Pattern: String) return Boolean; generic with procedure Visit (Full_Name, Phone_Number, Address: String; Stop: out Boolean); procedure Iterate (Name_Pattern: String); end Directory;
The Directory is an object consisting of data (the telephone numbers and addresses, presumably held in an external file or database) and behavior (it can look an entry up and traverse all the entries matching a Name_Pattern, calling Visit on each).
A simple package provides for encapsulation (the inner workings of the directory are hidden) and a pair of subprograms provide the behavior.
This pattern is appropriate when only one object of a certain type must exist; there is, therefore, no need for type extension or polymorphism.
Primitive operationsEdit
For the following, we need the definition of primitive operations:
The set of primitive operations of a type T consists of those subprograms that:
- are declared immediately within the same package as the type (not within a nested package nor a child package);
- take a parameter of the type or, for functions, return an object of the type;
- take an access parameter of the type or, for functions, return an access value of the type.
(Also predefined operators like equality "=" are primitive operations.)
An operation can be primitive on two or more types, but only on one tagged type. The following example would be illegal if also B were tagged.
package P is type A is tagged private; type B is private; procedure Proc (This: A; That: B); -- primitive on A and B end P;
Note, however, that this does not limit the number of parameters of a tagged type. For example, following definition is legal.
package P is type A is tagged private; procedure Proc (This, That: A); -- primitive only on A end P;
Primitive operations of tagged types are dispatching operations. Whether a call to such a primitive operation is in effect dispatching or statically bound, depends on the context (see below). Note that in a dispatching call both actual parameters of the last example must have the same tag (i.e. the same type); Constraint_Error will be called if the tag check fails.
Derived typesEdit
Type derivation has been part of Ada since the very start.
package P is type T is private; function Create (Data: Boolean) return T; -- primitive procedure Work (Object : in out T); -- primitive procedure Work (Pointer: access T); -- primitive type Acc_T is access T; procedure Proc (Pointer: Acc_T); -- not primitive private type T is record Data: Boolean; end record; end P;
The above example creates a type T that contains data (here just a Boolean but it could be anything) and behavior consisting of some subprograms. It also demonstrates encapsulation by placing the details of the type T in the private part of the package.
The primitive operations of T are the function Create, the overloaded procedures Work, and the predefined "=" operator; Proc is not primitive, since it has an access type on T as parameter — don't confuse this with an access parameter, as used in the second procedure Work. When deriving from T, the primitive operations are inherited.
with P; package Q is type Derived is new P.T; end Q;
The type Q.Derived has the same data and the same behavior as P.T; it inherits both the data and the subprograms. Thus it is possible to write:
with Q; procedure Main is Object: Q.Derived := Q.Create (Data => False); begin Q.Work (Object); end Main;
Inherited operations may be overridden and new operations added, but the rules (Ada 83) unfortunaltely are somewhat different from the rules for tagged types (Ada 95).
Admittedly, the reasons for writing this may seem obscure. The purpose of this kind of code is to have objects of types P.T and Q.Derived, which are not compatible:
Ob1: P.T; Ob2: Q.Derived; Ob1 := Ob2; -- illegal Ob1 := P.T (Ob2); -- but convertible Ob2 := Q.Derived (Ob1); -- in both directions
This feature is not used very often (it's used e.g. for declaring types reflecting physical dimensions) but I present it here to introduce the next step: type extension.
Type extensionsEdit
Type extensions are an Ada 95 amendment.
A tagged type provides support for dynamic polymorphism and type extension. A tagged type bears a hidden tag that identifies the type at run-time. Apart from the tag, a tagged record is like any other record, so it can contain arbitrary data.
package Person is type Object is tagged record Name : String (1 .. 10); Gender : Gender_Type; end record; procedure Put (O : Object); end Person;
As you can see, a
Person.Object is an object in the sense that it has data and behavior (the procedure
Put). However, this object does not hide its data; any program unit that has a
with Person clause can read and write the data in a Person.Object directly. This breaks encapsulation and also illustrates that Ada completely separates the concepts of encapsulation and type. Here is a version of Person.Object that encapsulates its data:
package Person is type Object is tagged private; procedure Put (O : Object); private type Object is tagged record Name : String (1 .. 10); Gender : Gender_Type; end record; end Person;
Because the type Person.Object is tagged, it is possible to create a record extension, which is a derived type with additional data.
with Person; package Programmer is type Object is new Person.Object with private; private type Object is new Person.Object with record Skilled_In : Language_List; end record; end Programmer;
The type
Programmer.Object inherits the data and behavior, i.e. the type's primitive operations, from
Person.Object; it is thus possible to write:
with Programmer; procedure Main is Me : Programmer.Object; begin Programmer.Put (Me); Me.Put; -- equivalent to the above, Ada 2005 only end Main;
So the declaration of the type
Programmer.Object, as a record extension of
Person.Object, implicitly declares a
procedure Put that applies to a
Like in the case of untagged types, objects of type Person and Programmer are convertible. However, where untagged objects are convertible in either direction, conversion of tagged types only works in the direction to the root. (Conversion away from the root would have to add components out of the blue.) Such a conversion is called a view conversion, because components are not lost, they only become invisible.
Extension aggregates have to be used if you go away from the root.
Now that we have introduced tagged types, record extensions and primitive operations, it becomes possible to understand overriding. In the examples above, we introduced a type
Person.Object with a primitive operation called
Put. Here is the body of the package:
with Ada.Text_IO; package body Person is procedure Put (O : Object) is begin Ada.Text_IO.Put (O.Name); Ada.Text_IO.Put (" is a "); Ada.Text_IO.Put_Line (Gender_Type'Image (O.Gender)); end Put; end Person;
As you can see, this simple operation prints both data components of the record type to standard output. Now, remember that the record extension
Programmer.Object has an additional data member. If we write:
with Programmer; procedure Main is Me : Programmer.Object; begin Programmer.Put (Me); Me.Put; -- equivalent to the above, Ada 2005 only end Main;
then the program will call the inherited primitive operation
Put, which will print the name and gender but not the additional data. In order to provide this extra behavior, we must override the inherited procedure
Put like this:
with Person; package Programmer is type Object is new Person.Object with private; overriding -- Optional keyword, new in Ada 2005 procedure Put (O : Object); private type Object is new Person.Object with record Skilled_In : Language_List; end record; end Programmer; package body Programmer is procedure Put (O : Object) is begin Person.Put (Person.Object (O)); -- view conversion to the ancestor type Put (O.Skilled_In); -- presumably declared in the same package as Language_List end Put; end Programmer;
Programmer.Put overrides
Person.Put; in other words it replaces it completely. Since the intent is to extend the behavior rather than replace it,
Programmer.Put calls
Person.Put as part of its behavior. It does this by converting its parameter from the type
Programmer.Object to its ancestor type
Person.Object. This construct is a view conversion; contrary to a normal type conversion, it does not create a new object and does not incur any run-time cost. Of course, it is optional that an overriding operation call its ancestor; there are cases where the intent is indeed to replace, not extend, the inherited behavior.
(Note that also for untagged types, overriding of inherited operations is possible. The reason why it's discussed here is that derivation of untagged types is done rather seldom.)
Polymorphism, class-wide programming and dynamic dispatchingEdit
The full power of object orientation is realized by polymorphism, class-wide programming and dynamic dispatching, which are different words for the same, single concept. To explain this concept, let us extend the example from the previous sections, where we declared a base tagged type
Person.Object with a primitive operation
Put and a record extension
Programmer.Object with additional data and an overriding primitive operation
Now, let us imagine a collection of persons. In the collection, some of the persons are programmers. We want to traverse the collection and call
Put on each person. When the person under consideration is a programmer, we want to call
Programmer.Put; when the person is not a programmer, we want to call
Person.Put. This, in essence, is polymorphism, class-wide programming and dynamic dispatching.
Ada implements this concept by means of class-wide types.
Each tagged type, such as
Person.Object, has a corresponding class of types which is the set of types comprising the type
Person.Object itself and all types that extend
Person.Object. In our example, this class consists of two types:
Ada 95 defines the
Person.Object'Class attribute to denote the corresponding class-wide type. In other words:
declare Someone : Person.Object'Class := ...; -- to be expanded later begin Someone.Put; -- dynamic dispatching end;
The declaration of Someone denotes an object that may be of either type,
Person.Object or
Programmer.Object. Consequently, the call to the primitive operation
Put dispatches dynamically to either
Person.Put or
The only problem is that, since we don't know whether Someone is a programmer or not, we don't know how many data components Someone has, either, and therefore we don't know how many bytes Someone takes in memory. For this reason, the class-wide type
Person.Object'Class is indefinite. It is impossible to declare an object of this type without giving some constraint. It is, however, possible to:
- declare an object of a class-wide with an initial value (as above). The object is then constrained by its initial value.
- declare an access value to such an object (because the access value has a known size);
- pass objects of a class-wide type as parameters to subprograms
- assign an object of a specific type (in particular, the result of a function call) to a variable of a class-wide type.
With this knowledge, we can now build a polymorphic collection of persons; in this example we will quite simply create an array of access values to persons:
with Person; procedure Main is type Person_Access is access Person.Object'Class; type Array_Of_Persons is array (Positive range <>) of Person_Access; function Read_From_Disk return Array_Of_Persons is separate; Everyone : constant Array_Of_Persons := Read_From_Disk; begin -- Main for K in Everyone'Range loop Everyone (K).all.Put; -- dereference followed by dynamic dispatching end loop; end Main;
The above procedure achieves our desired goal: it traverses the array of Persons and calls the procedure
Put that is appropriate for each person.
Advanced topic: How dynamic dispatching worksEdit
You don't need to know how dynamic dispatching works in order to use it effectively but, in case you are curious, here is an explanation.
The first component of each object in memory is the tag; this is why objects are of a tagged type rather than plain records. The tag really is an access value to a table; there is one table for each specific type.
The table contains access values to each primitive operation of the type.
In our example, since there are two types
Person.Object and
Programmer.Object, there are two tables, each containing a single access value.
The table for
Person.Object contains an access value to
Person.Put and the table for
Programmer.Object contains an access value to
When you compile your program, the compiler constructs both tables and places them in the program executable code.
Each time the program creates a new object of a specific type, it automatically sets its tag to point to the appropriate table.
Each time the program performs a dispatching call of a primitive operation, the compiler inserts object code that:
- dereferences the tag to find the table of primitive operations for the specific type of the object at hand
- dereferences the access value to the primitive operation
- calls the primitive operation.
Conversely, when the program performs a call where the parameter is a view conversion to an ancestor type, the compiler performs these two dereferences at compile time rather than run time: such a call is statically bound; the compiler emits code that directly calls the primitive operation of the ancestor type specified in the view conversion.
Dispatching is controlled by the (hidden) tag of the object. So what happens when a primitive operation
Op1 calls another primitive operation
Op2? Which operations will be called when the call to
Op1 is dispatching? Recalling the definitions, while
The primitive subprograms of a tagged type (…) are called dispatching operations.
3.9.2: Dispatching Operations of Tagged Types (Annotated)
still, some controlling tags are determined at compile time and, accordingly, determination of a body to be executed is static. Some controlling tags are determined at run-time and then determination of a body is dynamic.
Such a call is termed a dispatching call.
type Root is tagged private; procedure Op1 (This: Root); procedure Op2 (This: Root); type Derived is new Root with private; -- Derived inherits Op1 overriding procedure Op2 (This: Derived); procedure Op1 (This: Root) is begin ... Op2 (This); -- not redispatching Op2 (Root'Class (This)); -- redispatching This.Op2; -- not redispatching (new syntax since Ada 2005) (Root'Class (This)).Op2; -- redispatching (new syntax since Ada 2005) ... end Op1; D: Derived; C: Root'Class := D; Op1 (D); -- statically bound call Op1 (C); -- dispatching call D.Op1; -- statically bound call (new syntax since Ada 2005) C.Op1; -- dispatching call (new syntax since Ada 2005)
In this fragment,
Op1 is not overridden, whereas
Op2 is overridden. The body of
Op1 calls
Op2, thus which
Op2 will there be called if
Op1 is called with a parameter of type
Ada source text completely controls dispatching and redispatching. If you want redispatching, it is required that you state this explicitly by converting the parameter of the specific type to the class-wide type again. (Remember: View conversions never lose components, they just hide them. A conversion to a class-wide type can unhide them again.)
Thus the first call
Op1 (D) (statically bound, i.e., not dispatching) executes the inherited
Op1 — and within
Op1, then, the first call to
Op2 is also statically bound (there is no redispatching), parameter
This is a view conversion to specific type
Root. However, the second call is dispatching, since the parameter
This is converted to the class-wide type. The call dispatches to the overriding
The second call
Op1 (C) is a dispatching call to the inherited
Op1 and behaves exactly as the first.
To understand what happens here, the implicitly defined inherited
Op1 has a body calling the parent operation with a view conversion of the parameter:
procedure Op1 (This: Derived) is begin Op1 (Root (This)); -- view conversion end Op1;
This is very different from how other OO languages behave. In other OO languages, a method is either dispatching or not. In Ada, a routine is either available for dispatching or not. Whether or not dispatching is actually used for a given call depends on the way that the object's type is specified at that call point. For programmers accustomed to other OO languages, it can come as quite a surprise that calls from a dispatchable routine to other routines on the same object are, by default, not (dynamically) dispatched.
Similarly surprising but less commonly encountered, calls from a non-dispatchable routine for a tagged type to other routines on the same object are, by default, dispatched:
type Root is tagged private; procedure Op1 (This: Root'Class); procedure Op2 (This: Root); type Derived is new Root with private; -- Derived does not inherit Op1, rather Op1 is applicable to Derived. overriding procedure Op2 (This: Derived); procedure Op1 (This: Root'Class) is begin ... Op2 (This); -- dispatching Op2 (Root (This)); -- static call This.Op2; -- dispatching (new syntax since Ada 2005) (Root (This)).Op2; -- static call (new syntax since Ada 2005) ... end Op1; D: Derived; C: Root'Class := D; Op1 (D); -- static call Op1 (C); -- static call D.Op1; -- static call (new syntax since Ada 2005) C.Op1; -- static call (new syntax since Ada 2005)
Note that calls on Op1 are always static, since Op1 is not inherited. Its parameter type is classwide, so the operation is applicable to all types derived from Root. (Op2 has an entry for each type derived from Root in the dispatch table. There is no such dispatch table for Op1; rather there is only one such operation for all types in the class.)
Run-time type identificationEdit
Run-time type identification allows the program to (indirectly or directly) query the tag of an object at run time to determine which type the object belongs to. This feature, obviously, makes sense only in the context of polymorphism and dynamic dispatching, so works only on tagged types.
You can determine whether an object belongs to a certain class of types, or to a specific type, by means of the membership test in, like this:
type Base is tagged private; type Derived is new Base with private; type Leaf is new Derived with private; ... procedure Explicit_Dispatch (This : in Base'Class) is begin if This in Leaf then ... end if; if This in Derived'Class then ... end if; end Explicit_Dispatch;
Thanks to the strong typing rules of Ada, run-time type identification is in fact rarely needed; the distinction between class-wide and specific types usually allows the programmer to ensure objects are of the appropriate type without resorting to this feature.
Additionally, the reference manual defines
package Ada.Tags (RM 3.9(6/2)), attribute
'Tag (RM 3.9(16,18)), and
function Ada.Tags.Generic_Dispatching_Constructor (RM 3.9(18.2/2)), which enable direct manipulation with tags.
Creating ObjectsEdit
The Language Reference Manual's section on 3.3: Objects and Named Numbers (Annotated) states when an object is created, and destroyed again. This subsection illustrates how objects are created.
The LRM section starts,
Objects are created at run time and contain a value of a given type. An object can be created and initialized as part of elaborating a declaration, evaluating an allocator, aggregate, or function_call.
For example, assume a typical hierarchy of
object oriented types: a top-level type
Programmer type derived from
and possibly more kinds of persons. Each person has a name; assume
objects to have a
Name component.
Likewise, each
Person has a
Gender component.
Programmer type inherits the components and the operations
of the
Person type, so
Programmer objects
have a
Name and a
Gender component, too.
Programmer objects may have additional components specific
to programmers.
Objects of a tagged type are created the same way
as objects of any type.
The second LRM sentence says, for example, that an object will be created when you
declare a variable or a constant of a type.
For the tagged type
declare P: Person; begin Text_IO.Put_Line("The name is " & P.Name); end;
Nothing special so far. Just like any ordinary variable declaration
this O-O one is elaborated. The result of elaboration is an object named
of type
Person. However,
P has only default
name and gender value components. These are likely not useful ones.
One way of giving initial values to the object's components is
to assign an aggregate.
declare P: Person := (Name => "Scorsese", Gender => Male); begin Text_IO.Put_Line("The name is " & P.Name); end;
The parenthesized expression after := is called an aggregate (4.3: Aggregates (Annotated)).
Another way to create an object that is mentioned in the LRM paragraph is to call a function. An object will be created as the return value of a function call. Therefore, instead of using an aggregate of initial values, we might call a function returning an object.
Introducing proper O-O information
hiding, we change the package
containing the
Person type so that
becomes a private type. To enable clients of the package to construct
objects we declare a function that returns them. (The function may
do some interesting construction work on the objects. For instance, the aggregate above will most probably raise the exception Constraint_Error depending on the name string supplied; the function can mangle the name so that it matches the declaration of the component.) We also declare
a function that returns the name of
Person objects.
package Persons is type Person is tagged private; function Make (Name: String; Sex: Gender_Type) return Person; function Name (P: Person) return String; private type Person is tagged record Name : String (1 .. 10); Gender : Gender_Type; end record; end Persons;
Calling the
Make function results in an
object which can be used for initialization.
Since the
Person type is private we can no longer refer to the
component of
But there is a corresponding function
Name declared
with type
Person making it a socalled primitive operation.
(The component and the function in this example are both named
However, we can choose a different name for either
if we want.)
declare P: Person := Make (Name => "Orwell", Sex => Male); begin Text_IO.Put_Line("The name is " & Name(P)); end;
Objects can be copied into another. The target object is first destroyed.
Then the component values of the source object are assigned to the
corresponding components of the target object. In the following example,
the default initialized
P gets a copy of one of the objects
created by the
Make calls.
declare P: Person; begin if 2001 > 1984 then P := Make (Name => "Kubrick", Sex => Male); else P := Make (Name => "Orwell", Sex => Male); end if; Text_IO.Put_Line("The name is " & Name(P)); end;
So far there is no mention of the
Programmer type
derived from
There is no polymorphism yet, and likewise initialization
does not yet mention inheritance.
Before dealing with
Programmer objects and their initialization
a few words about class-wide types are in order.
More details on primitive operationsEdit
Remember what we said before about "Primitive Operations". Primitive operations are:
- subprograms taking a parameter of the tagged type;
- functions returning an object of the tagged type;
- subprograms taking a parameter of an anonymous access type to the tagged type;
- In Ada 2005 only, functions returning an anonymous access type to the tagged type;
Additionally, primitive operations must be declared before the type is frozen (the concept of freezing will be explained later):
package X is type Object is tagged null record; procedure Primitive_1 (This : in Object); procedure Primitive_2 (That : out Object); procedure Primitive_3 (Me : in out Object); procedure Primitive_4 (Them : access Object); function Primitive_5 return Object; function Primitive_6 (Everyone : Boolean) return access Object; end X;
All of these subprograms are primitive operations.
A primitive operation can also take parameters of the same or other types; also, the controlling operand does not have to be the first parameter:
package X is type Object is tagged null record; procedure Primitive_1 (This : in Object; Number : in Integer); procedure Primitive_2 (You : in Boolean; That : out Object); procedure Primitive_3 (Me, Her : in out Object); end X;
The definition of primitive operations specifically excludes named access types and class-wide types as well as operations not defined immediately in the same declarative region. Counter-examples:
package X is type Object is tagged null record; type Object_Access is access Object; type Object_Class_Access is access Object'Class; procedure Not_Primitive_1 (This : in Object'Class); procedure Not_Primitive_2 (This : in out Object_Access); procedure Not_Primitive_3 (This : out Object_Class_Access); function Not_Primitive_4 return Object'Class; package Inner is procedure Not_Primitive_5 (This : in Object); end Inner; end X;
Advanced topic: Freezing rulesEdit
Freezing rules (ARM 13.14) are perhaps the most complex part of the Ada language definition; this is because the standard tries to describe freezing as unambiguously as possible. Also, that part of the language definition deals with freezing of all entities, including complicated situations like generics and objects reached by dereferencing access values. You can, however, get an intuitive understanding of freezing of tagged types if you understand how dynamic dispatching works. In that section, we saw that the compiler emits a table of primitive operations for each tagged type. The point in the program text where this happens is the point where the tagged type is frozen, i.e. the point where the table becomes complete. After the type is frozen, no more primitive operations can be added to it.
This point is the earliest of:
- the end of the package spec where the tagged type is declared
- the appearance of the first type derived from the tagged type
package X is type Object is tagged null record; procedure Primitive_1 (This: in Object); -- this declaration freezes Object type Derived is new Object with null record; -- illegal: declared after Object is frozen procedure Primitive_2 (This: in Object); end X;
Intuitively: at the point where Derived is declared, the compiler starts a new table of primitive operations for the derived type. This new table, initially, is equal to the table of the primitive operations of the parent type,
Object. Hence,
Object must freeze.
- the declaration of a variable of the tagged type
package X is type Object is tagged null record; procedure Primitive_1 (This: in Object); V: Object; -- this declaration freezes Object
-- illegal: Primitive operation declared after Object is frozen procedure Primitive_2 (This: in Object); end X;
Intuitively: after the declaration of
V, it is possible to call any of the primitive operations of the type on
V. Therefore, the list of primitive operations must be known and complete, i.e. frozen.
- The completion (not the declaration, if any) of a constant of the tagged type:
package X is type Object is tagged null record; procedure Primitive_1 (This: in Object); -- this declaration does NOT freeze Object Deferred_Constant: constant Object; procedure Primitive_2 (This : in Object); -- OK private
-- only the completion freezes Object Deferred_Constant: constant Object := (null record); -- illegal: declared after Object is frozen procedure Primitive_3 (This: in Object); end X;
New features of Ada 2005Edit
This language feature is only available from Ada 2005 on.
Ada 2005 adds overriding indicators, allows anonymous access types in more places and offers the object.method notation.
Overriding indicatorsEdit
The new keyword overriding can be used to indicate whether an operation overrides an inherited subprogram or not. Its use is optional because of upward-compatibility with Ada 95. For example:
package X is type Object is tagged null record; function Primitive return access Object; -- new in Ada 2005 type Derived_Object is new Object with null record; not overriding -- new optional keywords in Ada 2005 procedure Primitive (This : in Derived_Object); -- new primitive operation overriding function Primitive return access Derived_Object; end X;
The compiler will check the desired behaviour.
This is a good programming practice because it avoids some nasty bugs like not overriding an inherited subprogram because the programmer spelt the identifier incorrectly, or because a new parameter is added later in the parent type.
It can also be used with abstract operations, with renamings, or when instantiating a generic subprogram:
not overriding procedure Primitive_X (This : in Object) is abstract; overriding function Primitive_Y return Object renames Some_Other_Subprogram; not overriding procedure Primitive_Z (This : out Object) is new Generic_Procedure (Element => Integer);
Object.Method notationEdit
We have already seen this notation:
package X is type Object is tagged null record; procedure Primitive (This: in Object; That: in Boolean); end X;
with X; procedure Main is Obj : X.Object; begin Obj.Primitive (That => True); -- Ada 2005 object.method notation end Main;
This notation is only available for primitive operations where the controlling parameter is the first parameter.
Abstract typesEdit
A tagged type can also be abstract (and thus can have abstract operations):
package X is type Object is abstract tagged …; procedure One_Class_Member (This : in Object); procedure Another_Class_Member (This : in out Object); function Abstract_Class_Member return Object is abstract; end X;
An abstract operation cannot have any body, so derived types are forced to override it (unless those derived types are also abstract). See next section about interfaces for more information about this.
The difference with a non-abstract tagged type is that you cannot declare any variable of this type. However, you can declare an access to it, and use it as a parameter of a class-wide operation.
Multiple Inheritance via InterfacesEdit
This language feature is only available from Ada 2005 on.
Interfaces allow for a limited form of multiple inheritance (taken from Java). On a semantic level they are similar to an "abstract tagged null record" as they may have primitive operations but cannot hold any data and thus these operations cannot have a body, they are either declared abstract or null. Abstract means the operation has to be overridden, null means the default implementation is a null body, i.e. one that does nothing.
An interface is declared with:
package Printable is type Object is interface; procedure Class_Member_1 (This : in Object) is abstract; procedure Class_Member_2 (This : out Object) is null; end Printable;
You implement an interface by adding it to a concrete class:
with Person; package Programmer is type Object is new Person.Object and Printable.Object with record Skilled_In : Language_List; end record; overriding procedure Class_Member_1 (This : in Object); not overriding procedure New_Class_Member (This : Object; That : String); end Programmer;
As usual, all inherited abstract operations must be overridden although null subprograms ones need not.
Such a type may implement a list of interfaces (called the progenitors), but can have only one parent. The parent may be a concrete type or also an interface.
type Derived is new Parent and Progenitor_1 and Progenitor_2 ... with ...;
Multiple Inheritance via Mix-inEdit
Ada supports multiple inheritance of interfaces (see above), but only single inheritance of implementation. This means that a tagged type can implement multiple interfaces but can only extend a single ancestor tagged type.
This can be problematic if you want to add behavior to a type that already extends another type; for example, suppose you have
type Base is tagged private; type Derived is new Base with private;
and you want to make
Derived controlled, i.e. add the behavior that
Derived controls its initialization, assignment and finalization. Alas you cannot write:
type Derived is new Base and Ada.Finalization.Controlled with private; -- illegal
Ada.Finalization for historical reasons does not define interfaces
Controlled and
Limited_Controlled, but abstract types.
If your base type is not limited, there is no good solution for this; you have to go back to the root of the class and make it controlled. (The reason will become obvious presently.)
For limited types however, another solutions is the use of a mix-in:
type Base is tagged limited private; type Derived; type Controlled_Mix_In (Enclosing: access Derived) is new Ada.Finalization.Limited_Controlled with null record; overriding procedure Initialize (This: in out Controlled_Mix_In); overriding procedure Finalize (This: in out Controlled_Mix_In); type Derived is new Base with record Mix_In: Controlled_Mix_In (Enclosing => Derived'Access); -- special syntax here -- other components here... end record;
This special kind of mix-in is an object with an access discriminant that references its enclosing object (also known as Rosen trick). In the declaration of the
Derived type, we initialize this discriminant with a special syntax:
Derived'Access really refers to an access value to the current instance of type
Derived. Thus the access discriminant allows the mix-in to see its enclosing object and all its components; therefore it can initialize and finalize its enclosing object:
overriding procedure Initialize (This: in out Controlled_Mix_In) is Enclosing: Derived renames This.Enclosing.all; begin -- initialize Enclosing... end Initialize;
and similarly for
The reason why this does not work for non-limited types is the self-referentiality via the discriminant. Imagine you have two variables of such a non-limited type and assign one to the other:
In an assignment statement,
Adjust is called only after
Finalize of the target
X and so cannot provide the new value of the discriminant. Thus
X.Mixin_In.Enclosing will inevitably reference
Now let's further extend our hierarchy:
type Further is new Derived with null record; overriding procedure Initialize (This: in out Further); overriding procedure Finalize (This: in out Further);
Oops, this does not work because there are no corresponding procedures for
Derived, yet - so let's quickly add them.
type Base is tagged limited private; type Derived; type Controlled_Mix_In (Enclosing: access Derived) is new Ada.Finalization.Limited_Controlled with null record; overriding procedure Initialize (This: in out Controlled_Mix_In); overriding procedure Finalize (This: in out Controlled_Mix_In); type Derived is new Base with record Mix_In: Controlled_Mix_In (Enclosing => Derived'Access); -- special syntax here -- other components here... end record; not overriding procedure Initialize (This: in out Derived); -- sic, they are new not overriding procedure Finalize (This: in out Derived); type Further is new Derived with null record; overriding procedure Initialize (This: in out Further); overriding procedure Finalize (This: in out Further);
We have of course to write
not overriding for the procedures on
Derived because there is indeed nothing they could override. The bodies are
not overriding procedure Initialize (This: in out Derived) is begin -- initialize Derived... end Initialize; overriding procedure Initialize (This: in out Controlled_Mix_In) is Enclosing: Derived renames This.Enclosing.all; begin Initialize (Enclosing); end Initialize;
To our dismay, we have to learn that
Initialize/Finalize for objects of type
Further will not be called, instead those for the parent
Derived. Why?
declare X: Further; -- Initialize (Derived (X)) is called here begin null; end; -- Finalize (Derived (X)) is called here
The reason is that the mix-in defines the local object
Enclosing to be of type
Derived in the renames-statement above.
To cure this, we have necessarily to use the dreaded redispatch (shown in different but equivalent notations):
overriding procedure Initialize (This: in out Controlled_Mix_In) is Enclosing: Derived renames This.Enclosing.all; begin Initialize (Derived'Class (Enclosing)); end Initialize; overriding procedure Finalize (This: in out Controlled_Mix_In) is Enclosing: Derived'Class renames Derived'Class (This.Enclosing.all); begin Enclosing.Finalize; end Finalize; declare X: Further; -- Initialize (X) is called here begin null; end; -- Finalize (X) is called here
Alternatively (and presumably better still) is to write
type Controlled_Mix_In (Enclosing: access Derived'Class) is new Ada.Finalization.Limited_Controlled with null record;
Then we automatically get redispatch and can omit the type conversions on
Class namesEdit
Both the class package and the class record need a name. In theory they may have the same name, but in practice this leads to nasty (because of unintutive error messages) name clashes when you use the
use clause. So over time three de facto naming standards have been commonly used.
The package is named by a plural noun and the record is named by the corresponding singular form.
package Persons is type Person is tagged record Name : String (1 .. 10); Gender : Gender_Type; end record; end Persons;
This convention is the usually used in Ada's built-in libraries.
Disadvantage: Some "multiples" are tricky to spell, especially for those of us who aren't native English speakers.
The package is named after the class, the record is just named Object.
package Person is type Object is tagged record Name : String (1 .. 10); Gender : Gender_Type; end record; end Person;
Most UML and IDL code generators use this technique.
Disadvantage: You can't use the
use clause on more than one such class packages at any one time. However you can always use the "type" instead of the package.
The package is named after the class, the record is postfixed with _Type.
package Person is type Person_Type is tagged record Name : String (1 .. 10); Gender : Gender_Type; end record; end Person;
Disadvantage: lots of ugly "_Type" postfixes.
Object-Oriented Ada for C++ programmersEdit
In C++, the construct
struct C {
virtual void v();
void w();
static void u();
is strictly equivalent to the following in Ada:
package P is type C is tagged null record; procedure V (This : in out C); -- primitive operation, will be inherited upon derivation procedure W (This : in out C'Class); -- not primitive, will not be inherited upon derivation procedure U; end P;
In C++, member functions implicitly take a parameter
this which is of type
C*. In Ada, all parameters are explicit. As a consequence, the fact that
u() does not take a parameter is implicit in C++ but explicit in Ada.
In C++,
this is a pointer. In Ada, the explicit
This parameter does not have to be a pointer; all parameters of a tagged type are implicitly passed by reference anyway.
Static dispatchingEdit
In C++, function calls dispatch statically in the following cases:
- the target of the call is an object type
- the member function is non-virtual
For example:
C object;
both dispatch statically. In particular, the static dispatch for v() may be confusing; this is because object is neither a pointer nor a reference. Ada behaves exactly the same in this respect, except that Ada calls this static binding rather than dispatching:
declare Object : P.C; begin Object.V; -- statically bound Object.W; -- statically bound end;
Dynamic dispatchingEdit
In C++, a function call dispatches dynamically if the two following conditions are met simultaneously:
- the target of the call is a pointer or a reference
- the member function is virtual.
For example:
C* object;
object->v(); // dynamic dispatch
object->w(); // static, non-virtual member function
object->u(); // illegal: static member function
C::u(); // static dispatch
In Ada, a primitive subprogram call dispatches (dynamically) if and only if:
- the target object is of a class-wide type;
Note: In Ada vernacular, the term dispatching always means dynamic.
For example:
declare Object : P.C'Class := ...; begin P.V (Object); -- dispatching P.W (Object); -- statically bound: not a primitive operation P.U; -- statically bound end;
As can be seen there is no need for access types or pointers to do dispatching in Ada. In Ada, tagged types are always passed by-reference to subprograms without the need for explicit access values.
Also note that in C++, the class serves as:
- the unit of encapsulation (Ada uses packages and visibility for this)
- the type, like in Ada.
As a consequence, you call C::u() in C++ because u() is encapsulated in C, but P.U in Ada since U is encapsulated in the package P, not the type C.
Class-wide and specific typesEdit
The most confusing part for C++ programmers is the concept of a "class-wide type". To help you understand:
- pointers and references in C++ are really, implicitly, class-wide;
- object types in C++ are really specific;
- C++ provides no way to declare the equivalent of:
type C_Specific_Access is access C;
- C++ provides no way to declare the equivalent of:
type C_Specific_Access_One is access C; type C_Specific_Access_Two is access C;
which, in Ada, are two different, incompatible types, possibly allocating their memory from different storage pools!
- In Ada, you do not need access values for dynamic dispatching.
- In Ada, you use access values for dynamic memory management (only) and class-wide types for dynamic dispatching (only).
- In C++, you use pointers and references both for dynamic memory management and for dynamic dispatching.
- In Ada, class-wide types are explicit (with
- In C++, class-wide types are implicit (with
in C++, a special syntax declares a constructor:
class C {
C(/* optional parameters */); // constructor
A constructor cannot be virtual. A class can have as many constructors, differentiated by their parameters, as necessary.
Ada does not have such constructors. Perhaps they were not deemed necessary since in Ada, any function that returns an object of the tagged type can serve as a kind of constructor. This is however not the same as a real constructor like the C++ one; this difference is most striking in cases of derivation trees (see Finalization below). The Ada constructor subprograms do not have to have a special name and there can be as many constructors as necessary; each function can take parameters as appropriate.
package P is type T is tagged private; function Make return T; -- constructor function To_T (From: Integer) return T; -- another constructor procedure Make (This: out T); -- not a constructor private ... end P;
If an Ada constructor function is also a primitive operation (as in the example above), it becomes abstract upon derivation and has to be overridden if the derived type is not itself abstract. If you do not want this, declare such functions in a nested scope.
In C++, one idiom is the copy constructor and its cousin the assignment operator:
class C {
C(const C& that); // copies "that" into "this"
C& operator= (const C& right); // assigns "right" to "this", which is "left"
This copy constructor is invoked implicitly on initialization, e.g.
C a = b; // calls the copy constructor
C c;
a = c; // calls the assignment operator
Ada provides a similar functionality by means of controlled types. A controlled type is one that extends the predefined type
with Ada.Finalization; package P is type T is new Ada.Finalization.Controlled with private; function Make return T; -- constructor private type T is ... end record; overriding procedure Initialize (This: in out T); overriding procedure Adjust (This: in out T); -- copy constructor end P;
Note that Initialize is not a constructor; it resembles the C++ constructor in some way, but is also very different. Suppose you have a type T1 derived from T with an appropriate overriding of Initialize. A real constructor (like the C++ one) would automatically first construct the parent components (T), then the child components. In Ada, this is not automatic. In order to mimic this in Ada, we have to write:
procedure Initialize (This: in out T1) is begin Initialize (T (This)); -- Don't forget this part! ... -- handle the new components here end Initialize;
The compiler inserts a call to Initialize after each object of type T is allocated when no initial value is given. It also inserts a call to Adjust after each assignment to the object. Thus, the declarations:
- allocate memory for A
- call Initialize (A)
- allocate memory for B
- copy the contents of X to B
- call Adjust (B)
Initialize (B) will not be called because of the explicit initialization.
So, the equivalent of a copy constructor is an overriding of Adjust.
If you would like to provide this functionality to a type that extends another, non-controlled type, see "Multiple Inheritance".
In C++, a destructor is a member function with only the implicit
this parameter:
class C {
virtual ~C(); // destructor
While a constructor cannot be virtual, a destructor must be virtual if the class is to be used with dynamic dispatch (has virtual methods or derives from a class with virtual methods). C++ classes do not use dynamic dispatch by default, so it can catch some programmers out and wreak havoc in their programs by simply forgetting the keyword
In Ada, the equivalent functionality is again provided by controlled types, by overriding the procedure Finalize:
with Ada.Finalization; package P is type T is new Ada.Finalization.Controlled with private; function Make return T; -- constructor private type T is ... end record; overriding procedure Finalize (This: in out T); -- destructor end P;
Because Finalize is a primitive operation, it is automatically "virtual"; you cannot, in Ada, forget to make a destructor virtual.
Encapsulation: public, private and protected membersEdit
In C++, the unit of encapsulation is the class; in Ada, the unit of encapsulation is the package. This has consequences on how an Ada programmer places the various components of an object type.
class C {
int a;
void public_proc();
int b;
int protected_func();
bool c;
void private_proc();
A way to mimic this C++ class in Ada is to define a hierarchy of types, where the base type is the public part, which must be abstract so that no stand-alone objects of this base type can be defined. It looks like so:
private with Ada.Finalization; package CPP is type Public_Part is abstract tagged record -- no objects of this type A: Integer; end record; procedure Public_Proc (This: in out Public_Part); type Complete_Type is new Public_Part with private; -- procedure Public_Proc (This: in out Complete_Type); -- inherited, implicitly defined private -- visible for children type Private_Part; -- declaration stub type Private_Part_Pointer is access Private_Part; type Private_Component is new Ada.Finalization.Controlled with record P: Private_Part_Pointer; end record; overriding procedure Initialize (X: in out Private_Component); overriding procedure Adjust (X: in out Private_Component); overriding procedure Finalize (X: in out Private_Component); type Complete_Type is new Public_Part with record B: Integer; P: Private_Component; -- must be controlled to avoid storage leaks end record; not overriding procedure Protected_Proc (This: Complete_Type); end CPP;
The private part is defined as a stub only, its completion is hidden in the body. In order to make it a component of the complete type, we have to use a pointer since the size of the component is still unknown (the size of a pointer is known to the compiler). With pointers, unfortunately, we incur the danger of memory leaks, so we have to make the private component controlled.
For a little test, this is the body, where the subprogram bodies are provided with identifying prints:
with Ada.Unchecked_Deallocation; with Ada.Text_IO; package body CPP is procedure Public_Proc (This: in out Public_Part) is -- primitive begin Ada.Text_IO.Put_Line ("Public_Proc" & Integer'Image (This.A)); end Public_Proc; type Private_Part is record -- complete declaration C: Boolean; end record; overriding procedure Initialize (X: in out Private_Component) is begin X.P := new Private_Part'(C => True); Ada.Text_IO.Put_Line ("Initialize " & Boolean'Image (X.P.C)); end Initialize; overriding procedure Adjust (X: in out Private_Component) is begin Ada.Text_IO.Put_Line ("Adjust " & Boolean'Image (X.P.C)); X.P := new Private_Part'(C => X.P.C); -- deep copy end Adjust; overriding procedure Finalize (X: in out Private_Component) is procedure Free is new Ada.Unchecked_Deallocation (Private_Part, Private_Part_Pointer); begin Ada.Text_IO.Put_Line ("Finalize " & Boolean'Image (X.P.C)); Free (X.P); end Finalize; procedure Private_Proc (This: in out Complete_Type) is -- not primitive begin Ada.Text_IO.Put_Line ("Private_Proc" & Integer'Image (This.A) & Integer'Image (This.B) & ' ' & Boolean'Image (This.P.P.C)); end Private_Proc; not overriding procedure Protected_Proc (This: Complete_Type) is -- primitive X: Complete_Type := This; begin Ada.Text_IO.Put_Line ("Protected_Proc" & Integer'Image (This.A) & Integer'Image (This.B)); Private_Proc (X); end Protected_Proc; end CPP;
We see that, due to the construction, the private procedure is not a primitive operation.
Let's define a child class so that the protected operation can be reached:
package CPP.Child is procedure Do_It (X: Complete_Type); -- not primitive end CPP.Child;
A child can look inside the private part of the parent and thus can see the protected procedure:
with Ada.Text_IO; package body CPP.Child is procedure Do_It (X: Complete_Type) is begin Ada.Text_IO.Put_Line ("Do_It" & Integer'Image (X.A) & Integer'Image (X.B)); Protected_Proc (X); end Do_It; end CPP.Child;
This is a simple test program, its output is shown below.
with CPP.Child; use CPP.Child, CPP; procedure Test_CPP is X, Y: Complete_Type; begin X.A := +1; Y.A := -1; Public_Proc (X); Do_It (X); Public_Proc (Y); Do_It (Y); X := Y; Public_Proc (X); Do_It (X); end Test_CPP;
This is the commented output of the test program:
Initialize TRUE Test_CPP: Initialize X Initialize TRUE and Y Public_Proc 1 | Public_Proc (X): A=1 Do_It 1-1073746208 | Do_It (X): B uninitialized Adjust TRUE | | Protected_Proc (X): Adjust local copy X of This Protected_Proc 1-1073746208 | | | Private_Proc 1-1073746208 TRUE | | | Private_Proc on local copy of This Finalize TRUE | | Protected_Proc (X): Finalize local copy X Public_Proc-1 | ditto for Y Do_It-1 65536 | | Adjust TRUE | | Protected_Proc-1 65536 | | Private_Proc-1 65536 TRUE | | Finalize TRUE | | Finalize TRUE | Assignment: Finalize target X.P.C Adjust TRUE | | Adjust: deep copy Public_Proc-1 | again for X, i.e. copy of Y Do_It-1 65536 | | Adjust TRUE | | Protected_Proc-1 65536 | | Private_Proc-1 65536 TRUE | | Finalize TRUE | | Finalize TRUE Finalize Y Finalize TRUE and X
You see that a direct translation of the C++ behaviour into Ada is difficult, if feasible at all. Methinks, the primitive Ada subprograms corresponds more to virtual C++ methods (in the example, they are not). Each language has its own idiosyncrasies which have to be taken into account, so that attempts to directly translate code from one into the other may not be the best approach.
De-encapsulation: friends and stream input-outputEdit
In C++, a friend function or class can see all members of the class it is a friend of. Friends break encapsulation and are therefore to be discouraged. In Ada, since packages and not classes are the unit of encapsulation, a "friend" subprogram is simply one that is declared in the same package as the tagged type.
In C++, stream input and output are the particular case where friends are usually necessary:
#include <iostream>
class C {
friend ostream& operator<<(ostream& output, C& arg);
int a, b;
bool c;
#include <iostream>
int main() {
C object;
cout << object;
return 0;
Ada does not need this construct because it defines stream input and output operations by default:
package P is pragma Elaborate_Body; -- explained below type C is tagged private; private type C is tagged record A, B : Integer; C : Boolean; end record; end P; with Ada.Text_IO.Text_Streams; with P; procedure Main is Object : P.C; begin P.C'Output (Stream => Ada.Text_IO.Text_Streams.Stream (Ada.Text_IO.Default_Output), Item => Object); end Main;
By default, the
Output attribute sends the tag of the object to the stream then calls the more basic
Write attribute, which sends the components to the stream in the same order as the declaration, i.e. A, B then C. It is possible to override the default implementation of the
Read and
Write attributes like this:
with Ada.Streams; package body P is procedure My_Write (Stream : not null access Ada.Streams.Root_Stream_Type'Class; Item : in C) is begin -- The default is to write A then B then C; here we change the ordering. Boolean'Write (Stream, Item.C); Integer'Write (Stream, Item.B); Integer'Write (Stream, Item.A); end My_Write; for C'Write use My_Write; -- override the default attribute end P;
In the above example,
P.C'output calls
P.C'Write which is overridden in the body of the package. Since the specification of package
P does not define any subprograms, it does not normally need a body, so a package body is forbidden. The
pragma Elaborate_Body tells the compiler that this package does have a body that is needed for other reasons.
Note that the stream IO attributes are not primitive operations of the tagged type; this is also the case in C++ where the friend operators are not, in fact, member functions of the type.
|class (as a unit of encapsulation)
|Tagged type
|class (of objects) (as a type) (not pointer or reference, which are class-wide)
|Primitive operation
|virtual member function
|pointer to the virtual table
|Class (of types)
|a tree of classes, rooted by a base class and including all the (recursively-)derived classes of that base class
|Class-wide type
|Class-wide operation
|static member function
|Access value to a specific tagged type
|Access value to a class-wide type
|pointer or reference to a class
See alsoEdit
Ada Reference ManualEdit
Ada 95Edit
- 3.8: Record Types (Annotated)
- 3.9: Tagged Types and Type Extensions (Annotated)
- 3.9.1: Type Extensions (Annotated)
- 3.9.2: Dispatching Operations of Tagged Types (Annotated)
- 3.9.3: Abstract Types and Subprograms (Annotated)
- 3.10: Access Types (Annotated)
Ada 2005Edit
- 3.8: Record Types (Annotated)
- 3.9: Tagged Types and Type Extensions (Annotated)
- 3.9.1: Type Extensions (Annotated)
- 3.9.2: Dispatching Operations of Tagged Types (Annotated)
- 3.9.3: Abstract Types and Subprograms (Annotated)
- 3.9.4: Interface Types (Annotated)
- 3.10: Access Types (Annotated)


text:
New Bangor Sports Radio Station, Website — 92.9 The Ticket — to Launch Jan. 1
BANGOR, Maine -- Sports fans in eastern Maine will have access to 24-7 sports programming over the air and online starting Jan. 1 with the launch of ESPN-affiliate 92.9 The Ticket (WEZQ-FM.)
The new format includes a local morning drive-time show hosted by Dale Duff and Clem LaBree, plus live, local play-by-play of high school games and the latest news from area college programs as well as the New England Patriots, Boston Bruins, Major League Baseball, the NBA and NCAA March Madness. The station will also serve as the flagship station for high school basketball tournament week this February.
The station's website, 929theticket.com, also is set to launch Jan. 1 and will feature live streaming of local games as well as stories, photos and video from around the world of sports. Until the launch date, you can find the 92.9 The Ticket on Facebook and Twitter.
The anticipated lineup is as follows: Dale and Clem's morning show, which will run from 6-8 a.m.,will be followed by Mike & Mike in the Morning (8-10 a.m.), The Herd with Colin Cowherd (10 a.m. to 1 p.m.), SVP & Russillo (1-4 p.m.), Coach & Co. (4-7 p.m.), Hill & Schlereth (7-10 p.m.) and SportsCenter Tonight from 10 p.m. to midnight.
Townsquare Media Bangor General Manager Tom Preble said he is excited about the change to the sports format.
"Sports radio is the fastest growing format in the nation. 92.9 The Ticket will reach many eastern Maine fans with 50,000 watts on the FM dial," he said. "Townsquare Media is also a leader in digital broadcasting and live events. This combination will make 92.9 The Ticket Maine's foremost sports authority on air, online and on mobile devices."
The 92.9 FM frequency is changing from an easy listening adult contemporary format.
Townsquare Media owns and operates five radio stations and websites in the Bangor market, including WBZN, WQCB, WWMJ, WEZQ and WDEA.


text:
January 2003 - Newsletter 72
Projects for 2003
Apart from the usual trotting up and down the country we always have to have something else up our sleeves to keep us out of mischief. This life is never dull if there is something around the corner.
We will be starting rehearsals for the new Grasmere Music CD very soon. Thank you for all your suggestions as to what it should include. I reckon there have been nigh on 80 tracks of music and song put forward so we will definitely not be short of material the only problem is editing them out so that we get a good balanced finished product. Some songs such as 'The Punch & Judy Man' are a must. It disappeared from our catalogue when 'Out In the Green Fields' was discontinued and people keep asking for it. It's one of those songs we've sung thousands of times but the pleasure of performing it never wears off. We will be in the studio from March 17th - 21st. Wish us luck.
When the weather cheers up a bit Jenny and Phil Biggs and I will be out with the camera again chatting people up for the second part of the 'River Frome' video. We have already done one interview just where the river runs into Poole Harbour. There is huge Roman pottery sight there. You literally couldn't move without treading on bits of Roman pot and we were very lucky to get in and film the kilns and the archaeologists at work before the sight was covered over again. We learnt of the excavation while filming our tame Roman Legionary in Dorchester for part one. The great thing about these projects is that everyone seems so willing to help, one story seems to lead to the next.
Christmas CD
We have had several goes over the years at persuading record companies that a Yetties Christmas recording would be a good bet but they have all been very wary about the short selling period so in the end we decided to go it alone. We certainly did the right thing there. Response has been tremendous partly due to an interview I did for Radio Solent at 7.35a.m. one Saturday morning just before Christmas. I must confess I did mutter to myself a little bit about the hour, especially as we had a fairly hectic day and late night on the Friday. I heaved myself out of bed good and early, knocked back a couple of mugs of tea so that the vocal chords would function and waited for the phone to ring. It all went very smoothly and no sooner had I snuggled back into bed than the phone rang again. 'Please mister can I have one of your Christmas CDs' was the message and from then on the phone didn't stop. By the time I'd finished posting them all off the Post Office staff must have thought I was feeling very generous and full of Christmas spirit.
'Children of Fiji' Charity
I'm delighted to say that your donations via our sponsored walk have now gone beyond the £700 mark. You really are the most generous people. Margaret and Peter Long who run the charity went out to Fiji for six weeks before Christmas and spent their time distributing books, stationery, etc. Fiji is not just one island, there are many scattered over a large area. To visit one particular school on Taveuni, for instance, involved a 12 hour overnight boat trip, followed by another 6 hour sea journey in a howling gale. Margaret and Peter really are the most dynamic duo I know. As soon as they got home they started collecting again. I can only admire such tenacity and wish them all the best for 2003.
Old Yetties LPs
My stock of these turns over at a high rate of knots and Halsway Manor Library benefits from the cash raised. If you have any you wish to pass on to good homes or would like to purchase some please ring 01935 814611.
Yetminster Fair - Saturday, 12th of July
Yes, I know it's early, but if you wish for information, tickets, camping facilities etc. then you need to get in contact with Derek Mott, Stonechat, High Street, Yetminster, Sherborne, Dorset, DT9 6LF. Tel. 01935 872123. If you wish to book a stall for the actual Fair to raise money for your particular charity or just to sell your own products Derek is also the man.
Halsway Manor Weekend 21st/23rd February
The beds in the actual house are sold out for this weekend but they might be able to put you up in local bed and breakfast if you are keen to come along. If you can't make the whole weekend you can join us for the Saturday night concert. Halsway Manor is the most delightful small Manor House you will ever come across and a visit is well worth while. If you want information about songs, music etc. then the library is there for you to do your research. For information, tickets etc. ring Halsway on 01984 618274.
New Bus
At some time in the next month or two Gordon Fry at West End Garage, Bruton is going to find us a new bus to replace the Mercedes we bought a couple of years ago. You would think with Mercedes reputation we were fairly safe in our decision to buy it but nothing could be further from the truth. It has more Gremlins than 'Ghostbusters' and despite the fact it has the three-pointed star on the bonnet Mercedes won't or can't do anything about it. They seem to have disowned it and it's costing us a fortune. Not to mention the fact that every morning I get up wondering what new malfunction it's going to throw at me today. Out first motorised transport was the Sartin family 1933 Ford 8 and I swear it was more reliable. Please note Mercedes KISS stands for 'Keep It Simple Stupid'. Don't build things you can't mend!
Cutting from a recent Sidmouth Herald
'Memory Lane, 25 Years Ago'
News Story: Some people will go to any length to see their favourite band playing, but for one 18 year old, Irene Marshall, travelling 580 miles from Scotland to Sidmouth had to be a record by local standards.
Irene, who originated from Sidmouth, first became a fan of the folk group The Yetties when she saw them play at the Sidmouth Folk Festival. During the festival she also met local resident Lorna McCrum with whom she kept in contact to find out the latest news on the band. When the Herald advertised The Yetties gig at the Radway Cinema Lorna sent Irene a cutting, not expecting she would want to come. Lorna was surprised to receive a telephone call asked her to get a ticket. Irene herself was in for a surprise when at the start of the gig she was given a bouquet of flowers by the band.
The gig itself was organised by the Sidmouth Round Table and raised £375 for a Christmas party for the elderly.
'Now there's dedication for you, I wonder where Lorna and Irene are now'